home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / system-config-printer / system-config-printer-kde.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-29  |  76KB  |  2,763 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. MIN_REFRESH_INTERVAL = 1
  5. domain = 'system-config-printer'
  6. import locale
  7. pkgdata = '/usr/share/' + domain
  8. import sys
  9. import os
  10. import time
  11. import traceback
  12. import re
  13. import tempfile
  14. import httplib
  15. import thread
  16. if os.path.exists('system-config-printer.ui'):
  17.     APPDIR = '.'
  18. else:
  19.     APPDIR = '/usr/share/system-config-printer'
  20. SYSTEM_CONFIG_PRINTER_DIR = '/usr/share/system-config-printer'
  21. if os.path.exists(SYSTEM_CONFIG_PRINTER_DIR + '/debug.py'):
  22.     sys.path.append(SYSTEM_CONFIG_PRINTER_DIR)
  23.  
  24. from PyQt4.QtCore import *
  25. from PyQt4.QtGui import *
  26. from PyQt4 import uic
  27. import gettext
  28. gettext.textdomain(domain)
  29.  
  30. def _(string):
  31.     return unicode(gettext.gettext(string), 'utf-8')
  32.  
  33.  
  34. def translate(self, prop):
  35.     '''reimplement method from uic to change it to use gettext'''
  36.     if prop.get('notr', None) == 'true':
  37.         return self._cstring(prop)
  38.     elif prop.text is None:
  39.         return ''
  40.     
  41.     text = prop.text.encode('UTF-8')
  42.     return _(text)
  43.  
  44. uic.properties.Properties._string = translate
  45. import cups
  46. cups.require('1.9.27')
  47. import config
  48. import cupshelpers
  49. from smburi import SMBURI
  50. from debug import *
  51. import dbus
  52. import dbus.mainloop.qt as dbus
  53. import dbus.service as dbus
  54. ellipsis = unichr(8230)
  55.  
  56. try:
  57.     try_CUPS_SERVER_REMOTE_ANY = cups.CUPS_SERVER_REMOTE_ANY
  58. except AttributeError:
  59.     try_CUPS_SERVER_REMOTE_ANY = '_remote_any'
  60.  
  61.  
  62. def validDeviceURI(uri):
  63.     '''Returns True is the provided URI is valid.'''
  64.     if uri.find(':/') > 0:
  65.         return True
  66.     
  67.     return False
  68.  
  69.  
  70. class GUI(QWidget):
  71.     '''our main class is the main window'''
  72.     printer_states = {
  73.         cups.IPP_PRINTER_IDLE: _('Idle'),
  74.         cups.IPP_PRINTER_PROCESSING: _('Processing'),
  75.         cups.IPP_PRINTER_BUSY: _('Busy'),
  76.         cups.IPP_PRINTER_STOPPED: _('Stopped') }
  77.     
  78.     def __init__(self, start_printer = None, change_ppd = False):
  79.         QWidget.__init__(self)
  80.         
  81.         try:
  82.             self.language = locale.getlocale(locale.LC_MESSAGES)
  83.             self.encoding = locale.getlocale(locale.LC_CTYPE)
  84.         except:
  85.             nonfatalException()
  86.             os.environ['LC_ALL'] = 'C'
  87.             locale.setlocale(locale.LC_ALL, '')
  88.             self.language = locale.getlocale(locale.LC_MESSAGES)
  89.             self.encoding = locale.getlocale(locale.LC_CTYPE)
  90.  
  91.         self.printer = None
  92.         self.conflicts = set()
  93.         if not self.printer or self.printer.getServer():
  94.             pass
  95.         self.connect_server = cups.getServer()
  96.         self.connect_user = cups.getUser()
  97.         self.password = ''
  98.         self.passwd_retry = False
  99.         self.widget_data_setting = { }
  100.         self.changed = set()
  101.         self.servers = set((self.connect_server,))
  102.         
  103.         try:
  104.             self.cups = cups.Connection()
  105.         except RuntimeError:
  106.             self.cups = None
  107.  
  108.         uic.loadUi(APPDIR + '/' + 'system-config-printer.ui', self)
  109.         self.show()
  110.         self.newPrinterGUI = np = NewPrinterGUI(self)
  111.         self.setConnected()
  112.         self.connect(self.mainlist, SIGNAL('itemSelectionChanged()'), self.on_tvMainList_cursor_changed)
  113.         self.connect(self.mainlist, SIGNAL('currentItemChanged (QTreeWidgetItem*, QTreeWidgetItem*)'), self.on_tvMainList_changed)
  114.         self.connect(self.chkServerBrowse, SIGNAL('stateChanged(int)'), self.on_server_widget_changed)
  115.         self.connect(self.chkServerShare, SIGNAL('stateChanged(int)'), self.on_server_widget_changed)
  116.         self.connect(self.chkServerShareAny, SIGNAL('stateChanged(int)'), self.on_server_widget_changed)
  117.         self.connect(self.chkServerRemoteAdmin, SIGNAL('stateChanged(int)'), self.on_server_widget_changed)
  118.         self.connect(self.chkServerAllowCancelAll, SIGNAL('stateChanged(int)'), self.on_server_widget_changed)
  119.         self.connect(self.chkServerLogDebug, SIGNAL('stateChanged(int)'), self.on_server_widget_changed)
  120.         self.connect(self.btnNewClass, SIGNAL('clicked()'), self.on_new_class_activate)
  121.         self.connect(self.btnNewPrinter, SIGNAL('clicked()'), self.on_new_printer_activate)
  122.         self.connect(self.entPDescription, SIGNAL('textEdited(const QString&)'), self.on_printer_changed)
  123.         self.connect(self.entPLocation, SIGNAL('textEdited(const QString&)'), self.on_printer_changed)
  124.         self.connect(self.entPDevice, SIGNAL('textEdited(const QString&)'), self.on_printer_changed)
  125.         self.connect(self.chkPEnabled, SIGNAL('stateChanged(int)'), self.on_printer_changed)
  126.         self.connect(self.chkPAccepting, SIGNAL('stateChanged(int)'), self.on_printer_changed)
  127.         self.connect(self.chkPShared, SIGNAL('stateChanged(int)'), self.on_printer_changed)
  128.         self.connect(self.cmbPErrorPolicy, SIGNAL('currentIndexChanged(int)'), self.on_printer_changed)
  129.         self.connect(self.cmbPOperationPolicy, SIGNAL('currentIndexChanged(int)'), self.on_printer_changed)
  130.         self.connect(self.cmbPStartBanner, SIGNAL('currentIndexChanged(int)'), self.on_printer_changed)
  131.         self.connect(self.cmbPEndBanner, SIGNAL('currentIndexChanged(int)'), self.on_printer_changed)
  132.         
  133.         try:
  134.             self.populateList(start_printer, change_ppd)
  135.         except cups.HTTPError:
  136.             (s,) = None
  137.             self.cups = None
  138.             self.setConnected()
  139.             self.populateList()
  140.             self.show_HTTP_Error(s)
  141.  
  142.         self.mainlist.header().hide()
  143.         self.btnNewPrinterNetwork.hide()
  144.         self.newPrinterNetworkLabel.hide()
  145.         self.btnNewPrinterSpecial.hide()
  146.         self.newPrinterSpecialLabel.hide()
  147.         self.btnNewPrinter.setText(_('New Printer'))
  148.         self.btnPrinterPropertiesApply.setIcon(QIcon(APPDIR + '/dialog-ok-apply.png'))
  149.         self.btnRevert.setIcon(QIcon(APPDIR + '/document-revert.png'))
  150.         self.newPrinterLabel.hide()
  151.         self.mainlist.setCurrentItem(self.settingsItem)
  152.         self.lblPOptions.hide()
  153.         self.lblPInstallOptions.hide()
  154.         self.setWindowIcon(QIcon(APPDIR + '/printer-128.png'))
  155.  
  156.     
  157.     def on_tvMainList_cursor_changed(self):
  158.         if self.changed:
  159.             return None
  160.         
  161.         items = self.mainlist.selectedItems()
  162.         if len(items) < 1:
  163.             return None
  164.         
  165.         item = items[0]
  166.         type = str(item.text(1))
  167.         name = str(item.text(0))
  168.         self.mainListSelectedType = type
  169.         self.mainListSelectedName = name
  170.         item_selected = True
  171.         if type == 'New':
  172.             self.ntbkMain.setCurrentIndex(0)
  173.         elif type == 'Settings':
  174.             self.ntbkMain.setCurrentIndex(1)
  175.             if self.cups:
  176.                 self.fillServerTab()
  177.             else:
  178.                 self.setDataButtonState()
  179.             item_selected = False
  180.         elif type in ('Printer', 'Class'):
  181.             
  182.             try:
  183.                 self.fillPrinterTab(name)
  184.                 self.fillPrinterOptions()
  185.                 self.setDataButtonState()
  186.             except RuntimeError:
  187.                 self.ntbkMain.setCurrentIndex(3)
  188.                 return None
  189.  
  190.             self.ntbkMain.setCurrentIndex(2)
  191.         elif type == 'None':
  192.             self.ntbkMain.setCurrentIndex(3)
  193.             self.setDataButtonState()
  194.             item_selected = False
  195.         
  196.  
  197.     
  198.     def printer_properties_response(self):
  199.         (name, type) = self.getSelectedItem()
  200.         if type in ('Printer', 'Class'):
  201.             return self.save_printer(self.printer)
  202.         elif type == 'Settings':
  203.             return self.save_serversettings()
  204.         
  205.  
  206.     
  207.     def on_tvMainList_changed(self, new, old):
  208.         '''about to change, offer to save'''
  209.         if self.changed:
  210.             answer = QMessageBox.question(self, 'Save Changes', 'Do you want to save changes?', QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, QMessageBox.Save)
  211.             if answer == QMessageBox.Save:
  212.                 self.printer_properties_response()
  213.             elif answer == QMessageBox.Discard:
  214.                 self.changed = set()
  215.             
  216.         
  217.  
  218.     
  219.     def busy(self, win = None):
  220.         
  221.         try:
  222.             if not win:
  223.                 win = self
  224.             
  225.             win.setCursor(Qt.WaitCursor)
  226.             QApplication.processEvents()
  227.         except:
  228.             nonfatalException()
  229.  
  230.  
  231.     
  232.     def ready(self, win = None):
  233.         
  234.         try:
  235.             if not win:
  236.                 win = self
  237.             
  238.             win.setCursor(Qt.ArrowCursor)
  239.             QApplication.processEvents()
  240.         except:
  241.             nonfatalException()
  242.  
  243.  
  244.     
  245.     def setConnected(self):
  246.         connected = bool(self.cups)
  247.         host = cups.getServer()
  248.         if host[0] == '/':
  249.             host = 'localhost'
  250.         
  251.         self.setWindowTitle(_('Printer configuration - %s') % host)
  252.         if connected:
  253.             status_msg = _('Connected to %s') % host
  254.         else:
  255.             status_msg = _('Not connected')
  256.         for widget in (self.chkServerBrowse, self.chkServerShare, self.chkServerRemoteAdmin, self.chkServerAllowCancelAll, self.chkServerLogDebug):
  257.             widget.setEnabled(connected)
  258.         
  259.         sharing = self.chkServerShare.isChecked()
  260.         self.chkServerShareAny.setEnabled(sharing)
  261.         
  262.         try:
  263.             del self.server_settings
  264.         except:
  265.             pass
  266.  
  267.  
  268.     
  269.     def populateList(self, start_printer = None, change_ppd = False):
  270.         old_name = ''
  271.         old_type = ''
  272.         select_path = None
  273.         if self.cups:
  274.             
  275.             try:
  276.                 self.printers = cupshelpers.getPrinters(self.cups)
  277.                 
  278.                 try:
  279.                     self.default_printer = self.cups.getDefault()
  280.                 except AttributeError:
  281.                     dests = self.cups.getDests()
  282.                     if dests.has_key((None, None)):
  283.                         self.default_printer = dests[(None, None)].name
  284.                     else:
  285.                         self.default_printer = None
  286.                 except:
  287.                     dests.has_key((None, None))
  288.  
  289.             except cups.IPPError:
  290.                 (e, m) = None
  291.                 self.show_IPP_Error(e, m)
  292.                 self.printers = { }
  293.                 self.default_printer = None
  294.             except:
  295.                 None<EXCEPTION MATCH>cups.IPPError
  296.             
  297.  
  298.         None<EXCEPTION MATCH>cups.IPPError
  299.         self.printers = { }
  300.         self.default_printer = None
  301.         local_printers = []
  302.         local_classes = []
  303.         remote_printers = []
  304.         remote_classes = []
  305.         for name, printer in self.printers.iteritems():
  306.             if printer.default:
  307.                 self.default_printer = name
  308.             
  309.             self.servers.add(printer.getServer())
  310.             if printer.remote:
  311.                 if printer.is_class:
  312.                     remote_classes.append(name)
  313.                 else:
  314.                     remote_printers.append(name)
  315.             printer.is_class
  316.             if printer.is_class:
  317.                 local_classes.append(name)
  318.                 continue
  319.             local_printers.append(name)
  320.         
  321.         local_printers.sort()
  322.         local_classes.sort()
  323.         remote_printers.sort()
  324.         remote_classes.sort()
  325.         if old_name != '' and old_name not in local_printers and old_name not in local_classes and old_name not in remote_printers and old_name not in remote_classes:
  326.             old_name = ''
  327.         
  328.         if self.default_printer != None and start_printer == None and old_name == '':
  329.             start_printer = self.default_printer
  330.         
  331.         if not start_printer:
  332.             start_printer = old_name
  333.         
  334.         expanded = {
  335.             '_printers': True,
  336.             '_classes': True,
  337.             '_remote_printers': True,
  338.             '_remote_classes': True }
  339.         self.mainlist.clear()
  340.         QTreeWidgetItem(self.mainlist, [
  341.             'New Printer',
  342.             'New'])
  343.         self.settingsItem = QTreeWidgetItem(self.mainlist, [
  344.             'Server Settings',
  345.             'Settings'])
  346.         for printers, text, name in ((local_printers, _('Local Printers'), '_printers'), (local_classes, _('Local Classes'), '_classes'), (remote_printers, _('Remote Printers'), '_remote_printers'), (remote_classes, _('Remote Classes'), '_remote_classes')):
  347.             if not printers:
  348.                 continue
  349.             
  350.             rootTreeItem = QTreeWidgetItem(self.mainlist, [
  351.                 text,
  352.                 name])
  353.             for printer_name in printers:
  354.                 if start_printer == None:
  355.                     start_printer = printer_name
  356.                 
  357.                 treeItem = QTreeWidgetItem(rootTreeItem, [
  358.                     printer_name,
  359.                     'Printer'])
  360.                 if printer_name == start_printer:
  361.                     treeItem.setSelected(True)
  362.                     expanded[name] = True
  363.                     continue
  364.             
  365.             if expanded[name]:
  366.                 rootTreeItem.setExpanded(True)
  367.                 continue
  368.         
  369.         self.on_tvMainList_cursor_changed()
  370.         self.setDataButtonState()
  371.  
  372.     
  373.     def on_printer_changed(self, text):
  374.         widget = self.sender()
  375.         if not widget:
  376.             return None
  377.         
  378.         if isinstance(widget, QCheckBox):
  379.             value = widget.isChecked()
  380.         elif isinstance(widget, QLineEdit):
  381.             value = unicode(widget.text())
  382.         elif isinstance(widget, QRadioButton):
  383.             value = widget.isChecked()
  384.         elif isinstance(widget, QComboBox):
  385.             value = unicode(widget.currentText())
  386.         else:
  387.             raise ValueError, 'Widget type not supported (yet)'
  388.         p = self.printer
  389.         old_values = {
  390.             self.entPDescription: p.info,
  391.             self.entPLocation: p.location,
  392.             self.entPDevice: p.device_uri,
  393.             self.chkPEnabled: p.enabled,
  394.             self.chkPAccepting: not (p.rejecting),
  395.             self.chkPShared: p.is_shared,
  396.             self.cmbPStartBanner: p.job_sheet_start,
  397.             self.cmbPEndBanner: p.job_sheet_end,
  398.             self.cmbPErrorPolicy: p.error_policy,
  399.             self.cmbPOperationPolicy: p.op_policy }
  400.         old_value = old_values[widget]
  401.         if old_value == value:
  402.             self.changed.discard(widget)
  403.         else:
  404.             self.changed.add(widget)
  405.         self.setDataButtonState()
  406.  
  407.     
  408.     def setDataButtonState(self):
  409.         
  410.         try:
  411.             if self.ppd and not bool(self.changed) and self.printer.enabled:
  412.                 pass
  413.             possible = not (self.printer.rejecting)
  414.             self.btnPrintTestPage.setEnabled(possible)
  415.             commands = self.printer.type & cups.CUPS_PRINTER_COMMANDS != 0
  416.             if commands:
  417.                 pass
  418.             self.btnSelfTest.setEnabled(possible)
  419.             if commands:
  420.                 pass
  421.             self.btnCleanHeads.setEnabled(possible)
  422.         except:
  423.             debugprint('exception in setDataButtonState')
  424.  
  425.         installablebold = False
  426.         optionsbold = False
  427.         if self.conflicts:
  428.             debugprint('Conflicts detected')
  429.             self.btnConflict.show()
  430.             for option in self.conflicts:
  431.                 if option.tab_label == self.lblPInstallOptions:
  432.                     installablebold = True
  433.                     continue
  434.                 optionsbold = True
  435.             
  436.         else:
  437.             self.btnConflict.hide()
  438.         installabletext = _('Installable Options')
  439.         optionstext = _('Printer Options')
  440.         if installablebold:
  441.             installabletext = '<b>%s</b>' % installabletext
  442.         
  443.         if optionsbold:
  444.             optionstext = '<b>%s</b>' % optionstext
  445.         
  446.         self.lblPInstallOptions.setText(installabletext)
  447.         self.lblPOptions.setText(optionstext)
  448.         self.btnPrinterPropertiesApply.setEnabled(len(self.changed) > 0)
  449.         self.btnRevert.setEnabled(len(self.changed) > 0)
  450.  
  451.     
  452.     def save_printer(self, printer, saveall = False):
  453.         class_deleted = False
  454.         name = printer.name
  455.         
  456.         try:
  457.             if not (printer.is_class) and self.ppd:
  458.                 self.getPrinterSettings()
  459.                 if self.ppd.nondefaultsMarked() or saveall:
  460.                     self.passwd_retry = False
  461.                     self.cups.addPrinter(name, ppd = self.ppd)
  462.                 
  463.             
  464.             if printer.is_class:
  465.                 pass
  466.             
  467.             location = unicode(self.entPLocation.text())
  468.             info = unicode(self.entPDescription.text())
  469.             device_uri = unicode(self.entPDevice.text())
  470.             if device_uri.find(ellipsis) != -1:
  471.                 device_uri = printer.device_uri
  472.             
  473.             enabled = self.chkPEnabled.isChecked()
  474.             accepting = self.chkPAccepting.isChecked()
  475.             shared = self.chkPShared.isChecked()
  476.             if info != printer.info or saveall:
  477.                 self.passwd_retry = False
  478.                 self.cups.setPrinterInfo(name, info)
  479.             
  480.             if location != printer.location or saveall:
  481.                 self.passwd_retry = False
  482.                 self.cups.setPrinterLocation(name, location)
  483.             
  484.             if not (printer.is_class):
  485.                 if device_uri != printer.device_uri or saveall:
  486.                     self.passwd_retry = False
  487.                     self.cups.setPrinterDevice(name, device_uri)
  488.                 
  489.             if enabled != printer.enabled or saveall:
  490.                 self.passwd_retry = False
  491.                 self.printer.setEnabled(enabled)
  492.             
  493.             if accepting == printer.rejecting or saveall:
  494.                 self.passwd_retry = False
  495.                 self.printer.setAccepting(accepting)
  496.             
  497.             if shared != printer.is_shared or saveall:
  498.                 self.passwd_retry = False
  499.                 self.printer.setShared(shared)
  500.             
  501.             job_sheet_start = unicode(self.cmbPStartBanner.currentText())
  502.             job_sheet_end = unicode(self.cmbPEndBanner.currentText())
  503.             error_policy = unicode(self.cmbPErrorPolicy.currentText())
  504.             op_policy = unicode(self.cmbPOperationPolicy.currentText())
  505.             if job_sheet_start != printer.job_sheet_start or job_sheet_end != printer.job_sheet_end or saveall:
  506.                 self.passwd_retry = False
  507.                 printer.setJobSheets(job_sheet_start, job_sheet_end)
  508.             
  509.             if error_policy != printer.error_policy or saveall:
  510.                 self.passwd_retry = False
  511.                 printer.setErrorPolicy(error_policy)
  512.             
  513.             if op_policy != printer.op_policy or saveall:
  514.                 self.passwd_retry = False
  515.                 printer.setOperationPolicy(op_policy)
  516.         except cups.IPPError:
  517.             (e, s) = None
  518.             self.show_IPP_Error(e, s)
  519.             return True
  520.  
  521.         self.changed = set()
  522.         if not self.__dict__.has_key('server_settings'):
  523.             
  524.             try:
  525.                 self.server_settings = self.cups.adminGetServerSettings()
  526.             nonfatalException()
  527.  
  528.         
  529.         if class_deleted:
  530.             self.populateList()
  531.         else:
  532.             printers = cupshelpers.getPrinters(self.cups)
  533.             this_printer = {
  534.                 name: printers[name] }
  535.             self.printers.update(this_printer)
  536.         return False
  537.  
  538.     
  539.     def getPrinterSettings(self):
  540.         for option in self.options.itervalues():
  541.             option.writeback()
  542.         
  543.  
  544.     
  545.     def on_btnPrintTestPage_clicked(self):
  546.         if self.test_button_cancels:
  547.             jobs = self.printer.testsQueued()
  548.             for job in jobs:
  549.                 debugprint('Canceling job %s' % job)
  550.                 
  551.                 try:
  552.                     self.cups.cancelJob(job)
  553.                 continue
  554.                 except cups.IPPError:
  555.                     (e, msg) = None
  556.                     self.show_IPP_Error(e, msg)
  557.                     continue
  558.                 
  559.  
  560.             
  561.             self.setTestButton(self.printer)
  562.             return None
  563.         
  564.         
  565.         try:
  566.             custom_testpage = None
  567.             opt = self.ppd.findOption('PageSize')
  568.             if opt:
  569.                 custom_testpage = os.path.join(pkgdata, 'testpage-%s.ps' % opt.defchoice.lower())
  570.             
  571.             if custom_testpage and os.path.exists(custom_testpage):
  572.                 debugprint('Printing custom test page ' + custom_testpage)
  573.                 job_id = self.cups.printTestPage(self.printer.name, file = custom_testpage)
  574.             else:
  575.                 debugprint('Printing default test page')
  576.                 job_id = self.cups.printTestPage(self.printer.name)
  577.             self.setTestButton(self.printer)
  578.             QMessageBox.information(self, _('Submitted'), _('Test page submitted as job %d') % job_id)
  579.         except cups.IPPError:
  580.             (e, msg) = None
  581.             if e == cups.IPP_NOT_AUTHORIZED and self.connect_server != 'localhost' and self.connect_server[0] != '/':
  582.                 self.lblError.set_markup('<span weight="bold" size="larger">' + _('Not possible') + '</span>\n\n' + _('The remote server did not accept the print job, most likely because the printer is not shared.'))
  583.                 self.ErrorDialog.set_transient_for(self.MainWindow)
  584.                 self.ErrorDialog.run()
  585.                 self.ErrorDialog.hide()
  586.             else:
  587.                 self.show_IPP_Error(e, msg)
  588.         except:
  589.             self.connect_server[0] != '/'
  590.  
  591.  
  592.     on_btnPrintTestPage_clicked = pyqtSignature('')(on_btnPrintTestPage_clicked)
  593.     
  594.     def maintenance_command(self, command):
  595.         (tmpfd, tmpfname) = tempfile.mkstemp()
  596.         os.write(tmpfd, '#CUPS-COMMAND\n%s\n' % command)
  597.         os.close(tmpfd)
  598.         
  599.         try:
  600.             format = 'application/vnd.cups-command'
  601.             job_id = self.cups.printTestPage(self.printer.name, format = format, file = tmpfname, user = self.connect_user)
  602.             self.lblInfo.set_markup('<span weight="bold" size="larger">' + _('Submitted') + '</span>\n\n' + _('Maintenance command submitted as job %d') % job_id)
  603.             self.InfoDialog.set_transient_for(self.MainWindow)
  604.             self.InfoDialog.run()
  605.             self.InfoDialog.hide()
  606.         except cups.IPPError:
  607.             (e, msg) = None
  608.             if e == cups.IPP_NOT_AUTHORIZED and self.printer.name != 'localhost':
  609.                 self.lblError.set_markup('<span weight="bold" size="larger">' + _('Not possible') + '</span>\n\n' + _('THe remote server did not accept the print job, most likely because the printer is not shared.'))
  610.                 self.ErrorDialog.set_transient_for(self.MainWindow)
  611.                 self.ErrorDialog.run()
  612.                 self.ErrorDialog.hide()
  613.             else:
  614.                 self.show_IPP_Error(e, msg)
  615.         except:
  616.             self.printer.name != 'localhost'
  617.  
  618.  
  619.     
  620.     def on_btnSelfTest_clicked(self):
  621.         self.maintenance_command('PrintSelfTestPage')
  622.  
  623.     on_btnSelfTest_clicked = pyqtSignature('')(on_btnSelfTest_clicked)
  624.     
  625.     def on_btnCleanHeads_clicked(self):
  626.         self.maintenance_command('Clean all')
  627.  
  628.     on_btnCleanHeads_clicked = pyqtSignature('')(on_btnCleanHeads_clicked)
  629.     
  630.     def fillComboBox(self, combobox, values, value):
  631.         combobox.clear()
  632.         for nr, val in enumerate(values):
  633.             combobox.addItem(val)
  634.             if val == value:
  635.                 combobox.setCurrentIndex(nr)
  636.                 continue
  637.         
  638.  
  639.     
  640.     def fillPrinterTab(self, name):
  641.         self.changed = set()
  642.         self.options = { }
  643.         self.conflicts = set()
  644.         printer = self.printers[name]
  645.         self.printer = printer
  646.         printer.getAttributes()
  647.         editable = not (self.printer.discovered)
  648.         editablePPD = not (self.printer.remote)
  649.         
  650.         try:
  651.             self.ppd = printer.getPPD()
  652.         except cups.IPPError:
  653.             (e, m) = None
  654.             self.show_IPP_Error(e, m)
  655.             self.ppd = False
  656.         except RuntimeError:
  657.             debugprint('Error!')
  658.             raise 
  659.  
  660.         for widget in (self.entPDescription, self.entPLocation, self.entPDevice):
  661.             widget.setReadOnly(not editable)
  662.         
  663.         for widget in (self.btnSelectDevice, self.btnChangePPD):
  664.             widget.setEnabled(editable)
  665.         
  666.         self.entPDescription.setText(printer.info)
  667.         self.entPLocation.setText(printer.location)
  668.         uri = printer.device_uri
  669.         if uri.startswith('smb://'):
  670.             (group, host, share, user, password) = SMBURI(uri = uri[6:]).separate()
  671.             if password:
  672.                 uri = 'smb://'
  673.                 if len(user) or len(password):
  674.                     uri += ellipsis
  675.                 
  676.                 uri += SMBURI(group = group, host = host, share = share).get_uri()
  677.                 self.entPDevice.setEnabled(False)
  678.             else:
  679.                 self.entPDevice.setEnabled(True)
  680.         
  681.         self.entPDevice.setText(uri)
  682.         self.changed.discard(self.entPDevice)
  683.         for widget in (self.lblPMakeModel2, self.lblPMakeModel, self.btnChangePPD, self.lblPDevice2, self.entPDevice, self.btnSelectDevice):
  684.             if printer.is_class:
  685.                 widget.hide()
  686.                 continue
  687.             widget.show()
  688.         
  689.         self.btnPMakeDefault.setEnabled(not (printer.default))
  690.         if printer.default:
  691.             self.lblPDefault.setText(_('This is the default printer'))
  692.         elif self.default_printer:
  693.             self.lblPDefault.setText(self.default_printer)
  694.         else:
  695.             self.lblPDefault.setText(_('No default printer set.'))
  696.         self.setTestButton(printer)
  697.         self.chkPEnabled.setChecked(printer.enabled)
  698.         self.chkPAccepting.setChecked(not (printer.rejecting))
  699.         self.chkPShared.setChecked(printer.is_shared)
  700.         
  701.         try:
  702.             if printer.is_shared:
  703.                 flag = cups.CUPS_SERVER_SHARE_PRINTERS
  704.                 publishing = int(self.server_settings[flag])
  705.                 if publishing:
  706.                     self.lblNotPublished.hide()
  707.                 else:
  708.                     self.lblNotPublished.show()
  709.             else:
  710.                 self.lblNotPublished.hide()
  711.         except:
  712.             self.lblNotPublished.hide()
  713.  
  714.         self.cmbPStartBanner.setEnabled(editable)
  715.         self.cmbPEndBanner.setEnabled(editable)
  716.         self.cmbPErrorPolicy.setEnabled(editable)
  717.         self.cmbPOperationPolicy.setEnabled(editable)
  718.         self.changed = set()
  719.         self.updatePrinterProperties()
  720.         self.setDataButtonState()
  721.  
  722.     
  723.     def fillPrinterOptions(self):
  724.         pass
  725.  
  726.     
  727.     def on_btnDelete_clicked(self):
  728.         (name, type) = self.getSelectedItem()
  729.         print name
  730.         if type == 'Printer':
  731.             message_format = _('Really delete printer %s?')
  732.         else:
  733.             message_format = _('Really delete class %s?')
  734.         cancel = QMessageBox.question(self, '', message_format % name, _('&Yes'), _('&No'), QString(), 0, 1)
  735.         if cancel:
  736.             return None
  737.         
  738.         
  739.         try:
  740.             self.cups.deletePrinter(name)
  741.         except cups.IPPError:
  742.             (e, msg) = None
  743.             self.show_IPP_Error(e, msg)
  744.  
  745.         self.changed = set()
  746.         self.populateList()
  747.         self.mainlist.setCurrentItem(self.mainlist.itemAt(0, 0))
  748.  
  749.     on_btnDelete_clicked = pyqtSignature('')(on_btnDelete_clicked)
  750.     
  751.     def on_btnPMakeDefault_clicked(self):
  752.         
  753.         try:
  754.             self.cups.setDefault(self.printer.name)
  755.         except cups.IPPError:
  756.             (e, msg) = None
  757.             self.show_IPP_Error(e, msg)
  758.             return None
  759.  
  760.         (tmpfd, tmpfname) = tempfile.mkstemp()
  761.         success = False
  762.         
  763.         try:
  764.             resource = '/admin/conf/lpoptions'
  765.             self.cups.getFile(resource, tmpfname)
  766.         except cups.HTTPError:
  767.             (s,) = None
  768.             
  769.             try:
  770.                 os.remove(tmpfname)
  771.             except OSError:
  772.                 pass
  773.  
  774.             if s != cups.HTTP_NOT_FOUND:
  775.                 self.show_HTTP_Error(s)
  776.                 return None
  777.             
  778.         except:
  779.             s != cups.HTTP_NOT_FOUND
  780.  
  781.         if success:
  782.             lines = file(tmpfname).readlines()
  783.             changed = False
  784.             i = 0
  785.             for line in lines:
  786.                 if line.startswith('Default '):
  787.                     name = line.split(' ')[1]
  788.                     if name != self.printer.name:
  789.                         lines[i] = 'Dest ' + line[8:]
  790.                         changed = True
  791.                     
  792.                 
  793.                 i += 1
  794.             
  795.             if changed:
  796.                 file(tmpfname, 'w').writelines(lines)
  797.                 
  798.                 try:
  799.                     self.cups.putFile(resource, tmpfname)
  800.                 except cups.HTTPError:
  801.                     (s,) = None
  802.                     os.remove(tmpfname)
  803.                     print s
  804.                     self.show_HTTP_Error(s)
  805.                     return None
  806.  
  807.                 self.reconnect()
  808.             
  809.         
  810.         
  811.         try:
  812.             os.remove(tmpfname)
  813.         except OSError:
  814.             pass
  815.  
  816.         
  817.         try:
  818.             self.populateList()
  819.         except cups.HTTPError:
  820.             (s,) = None
  821.             self.cups = None
  822.             self.setConnected()
  823.             self.populateList()
  824.             self.show_HTTP_Error(s)
  825.  
  826.  
  827.     on_btnPMakeDefault_clicked = pyqtSignature('')(on_btnPMakeDefault_clicked)
  828.     
  829.     def fillServerTab(self):
  830.         self.changed = set()
  831.         
  832.         try:
  833.             self.server_settings = self.cups.adminGetServerSettings()
  834.         except cups.IPPError:
  835.             (e, m) = None
  836.             self.show_IPP_Error(e, m)
  837.             self.tvMainList.get_selection().unselect_all()
  838.             self.on_tvMainList_cursor_changed(self.tvMainList)
  839.             return None
  840.  
  841.         for widget, setting in [
  842.             (self.chkServerBrowse, cups.CUPS_SERVER_REMOTE_PRINTERS),
  843.             (self.chkServerShare, cups.CUPS_SERVER_SHARE_PRINTERS),
  844.             (self.chkServerShareAny, try_CUPS_SERVER_REMOTE_ANY),
  845.             (self.chkServerRemoteAdmin, cups.CUPS_SERVER_REMOTE_ADMIN),
  846.             (self.chkServerAllowCancelAll, cups.CUPS_SERVER_USER_CANCEL_ANY),
  847.             (self.chkServerLogDebug, cups.CUPS_SERVER_DEBUG_LOGGING)]:
  848.             self.widget_data_setting[widget] = setting
  849.             self.disconnect(widget, SIGNAL('stateChanged(int)'), self.on_server_widget_changed)
  850.             if self.server_settings.has_key(setting):
  851.                 widget.setChecked(int(self.server_settings[setting]))
  852.                 widget.setEnabled(True)
  853.             else:
  854.                 widget.setChecked(False)
  855.                 widget.setEnabled(False)
  856.             self.connect(widget, SIGNAL('stateChanged(int)'), self.on_server_widget_changed)
  857.         
  858.         self.setDataButtonState()
  859.         self.on_server_changed(self.chkServerShare)
  860.  
  861.     
  862.     def on_server_widget_changed(self, value):
  863.         self.on_server_changed(self.sender())
  864.  
  865.     
  866.     def on_server_changed(self, widget):
  867.         setting = self.widget_data_setting[widget]
  868.         if self.server_settings.has_key(setting):
  869.             if str(int(widget.isChecked())) == self.server_settings[setting]:
  870.                 self.changed.discard(widget)
  871.             else:
  872.                 self.changed.add(widget)
  873.         
  874.         sharing = self.chkServerShare.isChecked()
  875.         if sharing:
  876.             pass
  877.         self.chkServerShareAny.setEnabled(self.server_settings.has_key(try_CUPS_SERVER_REMOTE_ANY))
  878.         self.setDataButtonState()
  879.  
  880.     
  881.     def save_serversettings(self):
  882.         setting_dict = self.server_settings.copy()
  883.         for widget, setting in [
  884.             (self.chkServerBrowse, cups.CUPS_SERVER_REMOTE_PRINTERS),
  885.             (self.chkServerShare, cups.CUPS_SERVER_SHARE_PRINTERS),
  886.             (self.chkServerShareAny, try_CUPS_SERVER_REMOTE_ANY),
  887.             (self.chkServerRemoteAdmin, cups.CUPS_SERVER_REMOTE_ADMIN),
  888.             (self.chkServerAllowCancelAll, cups.CUPS_SERVER_USER_CANCEL_ANY),
  889.             (self.chkServerLogDebug, cups.CUPS_SERVER_DEBUG_LOGGING)]:
  890.             if not self.server_settings.has_key(setting):
  891.                 continue
  892.             
  893.             setting_dict[setting] = str(int(widget.isChecked()))
  894.         
  895.         
  896.         try:
  897.             self.cups.adminSetServerSettings(setting_dict)
  898.         except cups.IPPError:
  899.             (e, m) = None
  900.             self.show_IPP_Error(e, m)
  901.             return True
  902.         except RuntimeError:
  903.             s = None
  904.             self.show_IPP_Error(None, s)
  905.             return True
  906.  
  907.         self.changed = set()
  908.         self.setDataButtonState()
  909.         time.sleep(1)
  910.         self.reconnect()
  911.         
  912.         try:
  913.             self.fillServerTab()
  914.         except:
  915.             nonfatalException()
  916.  
  917.  
  918.     
  919.     def on_new_printer_activate(self):
  920.         self.busy()
  921.         self.newPrinterGUI.init('printer')
  922.         self.ready()
  923.  
  924.     
  925.     def on_new_class_activate(self):
  926.         self.newPrinterGUI.init('class')
  927.  
  928.     
  929.     def on_btnSelectDevice_clicked(self):
  930.         self.newPrinterGUI.init('device')
  931.  
  932.     on_btnSelectDevice_clicked = pyqtSignature('')(on_btnSelectDevice_clicked)
  933.     
  934.     def on_btnChangePPD_clicked(self):
  935.         self.busy(self)
  936.         self.newPrinterGUI.init('ppd')
  937.         self.ready(self)
  938.  
  939.     on_btnChangePPD_clicked = pyqtSignature('')(on_btnChangePPD_clicked)
  940.     
  941.     def checkNPName(self, name):
  942.         if not name:
  943.             return False
  944.         
  945.         name = name.lower()
  946.         for printer in self.printers.values():
  947.             if not (printer.discovered) and printer.name.lower() == name:
  948.                 return False
  949.                 continue
  950.         
  951.         return True
  952.  
  953.     
  954.     def makeNameUnique(self, name):
  955.         '''Make a suggested queue name valid and unique.'''
  956.         name = name.replace(' ', '_')
  957.         name = name.replace('/', '_')
  958.         name = name.replace('#', '_')
  959.         if not self.checkNPName(name):
  960.             suffix = 2
  961.             while not self.checkNPName(name + str(suffix)):
  962.                 suffix += 1
  963.                 if suffix == 100:
  964.                     break
  965.                     continue
  966.             name += str(suffix)
  967.         
  968.         return name
  969.  
  970.     
  971.     def on_btnRevert_clicked(self):
  972.         self.changed = set()
  973.         self.on_tvMainList_cursor_changed()
  974.  
  975.     on_btnRevert_clicked = pyqtSignature('')(on_btnRevert_clicked)
  976.     
  977.     def on_btnPrinterPropertiesApply_clicked(self):
  978.         err = self.printer_properties_response()
  979.         if not err:
  980.             self.populateList()
  981.         else:
  982.             nonfatalException()
  983.  
  984.     on_btnPrinterPropertiesApply_clicked = pyqtSignature('')(on_btnPrinterPropertiesApply_clicked)
  985.     
  986.     def show_IPP_Error(self, exception, message):
  987.         if exception == cups.IPP_NOT_AUTHORIZED:
  988.             QMessageBox.critical(self, _('Not authorized'), _('The password may be incorrect.'))
  989.         else:
  990.             QMessageBox.critical(self, _('CUPS server error'), _("There was an error during the CUPS operation: '%s'.") % message)
  991.  
  992.     
  993.     def show_HTTP_Error(self, status):
  994.         if status == cups.HTTP_UNAUTHORIZED or status == cups.HTTP_FORBIDDEN:
  995.             QMessageBox.critical(self, _('Not authorized'), _('The password may be incorrect, or the server may be configured to deny remote administration.'))
  996.         elif status == cups.HTTP_BAD_REQUEST:
  997.             msg = _('Bad request')
  998.         elif status == cups.HTTP_NOT_FOUND:
  999.             msg = _('Not found')
  1000.         elif status == cups.HTTP_REQUEST_TIMEOUT:
  1001.             msg = _('Request timeout')
  1002.         elif status == cups.HTTP_UPGRADE_REQUIRED:
  1003.             msg = _('Upgrade required')
  1004.         elif status == cups.HTTP_SERVER_ERROR:
  1005.             msg = _('Server error')
  1006.         elif status == -1:
  1007.             msg = _('Not connected')
  1008.         else:
  1009.             msg = _('status %d') % status
  1010.         error_text = ('<span weight="bold" size="larger">' + _('CUPS server error') + '</span>\n\n' + _('There was an HTTP error: %s.')) % msg
  1011.         QMessageBox.critical(self, _('CUPS server error'), _('There was an HTTP error: %s.') % msg)
  1012.  
  1013.     
  1014.     def getSelectedItem(self):
  1015.         return (str(self.mainListSelectedName).decode('utf-8'), str(self.mainListSelectedType))
  1016.  
  1017.     
  1018.     def reconnect(self):
  1019.         '''Reconnect to CUPS after the server has reloaded.'''
  1020.         self.cups = None
  1021.         self.setConnected()
  1022.         cups.setServer(self.connect_server)
  1023.         cups.setUser(self.connect_user)
  1024.         attempt = 1
  1025.         while attempt <= 5:
  1026.             
  1027.             try:
  1028.                 self.cups = cups.Connection()
  1029.             continue
  1030.             except RuntimeError:
  1031.                 time.sleep(1)
  1032.                 attempt += 1
  1033.                 continue
  1034.             
  1035.  
  1036.             None<EXCEPTION MATCH>RuntimeError
  1037.         self.setConnected()
  1038.         self.passwd_retry = False
  1039.  
  1040.     
  1041.     def updatePrinterProperties(self):
  1042.         debugprint('update printer properties')
  1043.         printer = self.printer
  1044.         self.lblPMakeModel.setText(printer.make_and_model)
  1045.         state = self.printer_states.get(printer.state, _('Unknown'))
  1046.         reason = printer.other_attributes.get('printer-state-message', '')
  1047.         if len(reason) > 0:
  1048.             state += ' - ' + reason
  1049.         
  1050.         self.lblPState.setText(state)
  1051.         if len(self.changed) == 0:
  1052.             debugprint('no changes yet: full printer properties update')
  1053.             self.chkPEnabled.setEnabled(printer.enabled)
  1054.             self.chkPAccepting.setEnabled(not (printer.rejecting))
  1055.             self.chkPShared.setEnabled(printer.is_shared)
  1056.             (self.fillComboBox(self.cmbPStartBanner, printer.job_sheets_supported, printer.job_sheet_start),)
  1057.             self.fillComboBox(self.cmbPEndBanner, printer.job_sheets_supported, printer.job_sheet_end)
  1058.             self.fillComboBox(self.cmbPErrorPolicy, printer.error_policy_supported, printer.error_policy)
  1059.             self.fillComboBox(self.cmbPOperationPolicy, printer.op_policy_supported, printer.op_policy)
  1060.         
  1061.  
  1062.     
  1063.     def setTestButton(self, printer):
  1064.         if printer.testsQueued():
  1065.             self.test_button_cancels = True
  1066.             self.btnPrintTestPage.setText(_('Cancel Tests'))
  1067.             self.btnPrintTestPage.setEnabled(True)
  1068.         else:
  1069.             self.test_button_cancels = False
  1070.             self.btnPrintTestPage.setText(_('Print Test Page'))
  1071.             self.setDataButtonState()
  1072.  
  1073.     
  1074.     def getCurrentClassMembers(self, listwidget):
  1075.         count = listwidget.count()
  1076.         result = []
  1077.         for i in range(count):
  1078.             result.append(listwidget.item(i).text())
  1079.         
  1080.         result.sort()
  1081.         return result
  1082.  
  1083.     
  1084.     def moveClassMembers(self, treeview_from, treeview_to):
  1085.         rows = treeview_from.selectedItems()
  1086.         for row in rows:
  1087.             treeview_from.takeItem(treeview_from.row(row))
  1088.             treeview_to.addItem(row)
  1089.         
  1090.  
  1091.     
  1092.     def cupsPasswdCallback(self, querystring):
  1093.         return ''
  1094.         if self.passwd_retry or len(self.password) == 0:
  1095.             waiting = self.WaitWindow.get_property('visible')
  1096.             if waiting:
  1097.                 self.WaitWindow.hide()
  1098.             
  1099.             self.lblPasswordPrompt.set_label(self.prompt_primary + querystring)
  1100.             self.PasswordDialog.set_transient_for(self.MainWindow)
  1101.             self.entPasswd.grab_focus()
  1102.             result = self.PasswordDialog.run()
  1103.             self.PasswordDialog.hide()
  1104.             if waiting:
  1105.                 self.WaitWindow.show()
  1106.             
  1107.             while gtk.events_pending():
  1108.                 gtk.main_iteration()
  1109.             if result == gtk.RESPONSE_OK:
  1110.                 self.password = self.entPasswd.get_text()
  1111.             else:
  1112.                 self.password = ''
  1113.             self.passwd_retry = False
  1114.         else:
  1115.             self.passwd_retry = True
  1116.         return self.password
  1117.  
  1118.  
  1119.  
  1120. class NewPrinterGUI(QDialog):
  1121.     new_printer_device_tabs = {
  1122.         'parallel': 0,
  1123.         'usb': 0,
  1124.         'hal': 0,
  1125.         'beh': 0,
  1126.         'hp': 0,
  1127.         'hpfax': 0,
  1128.         'socket': 2,
  1129.         'ipp': 3,
  1130.         'http': 3,
  1131.         'lpd': 4,
  1132.         'scsi': 5,
  1133.         'serial': 6,
  1134.         'smb': 7 }
  1135.     ntbkNewPrinterPages = {
  1136.         'name': 0,
  1137.         'device': 1,
  1138.         'make': 2,
  1139.         'model': 3,
  1140.         'class-members': 4,
  1141.         'downloadable': -1 }
  1142.     
  1143.     def __init__(self, mainapp):
  1144.         QDialog.__init__(self, mainapp)
  1145.         self.mainapp = mainapp
  1146.         self.language = mainapp.language
  1147.         self.dialog_mode = ''
  1148.         self.WaitWindow = QMessageBox(self.mainapp)
  1149.         self.WaitWindow.setStandardButtons(QMessageBox.NoButton)
  1150.         uic.loadUi(APPDIR + '/' + 'new-printer.ui', self)
  1151.         self.connect(self.tvNPDevices, SIGNAL('itemSelectionChanged()'), self.on_tvNPDevices_cursor_changed)
  1152.         self.connect(self.tvNPMakes, SIGNAL('itemSelectionChanged()'), self.on_tvNPMakes_cursor_changed)
  1153.         self.connect(self.tvNPModels, SIGNAL('itemSelectionChanged()'), self.on_tvNPModels_cursor_changed)
  1154.         self.connect(self.entNPTDevice, SIGNAL('textEdited(const QString&)'), self.on_entNPTDevice_changed)
  1155.         self.connect(self.entSMBURI, SIGNAL('textEdited(const QString&)'), self.on_entSMBURI_changed)
  1156.         self.rbtnSMBAuthPrompt.setChecked(True)
  1157.         self.on_rbtnSMBAuthSet_toggled(False)
  1158.         self.connect(self.rbtnSMBAuthSet, SIGNAL('toggled(bool)'), self.on_rbtnSMBAuthSet_toggled)
  1159.         self.rbtnNPFoomatic.setChecked(True)
  1160.         self.connect(self.rbtnNPFoomatic, SIGNAL('toggled(bool)'), self.on_rbtnNPFoomatic_toggled)
  1161.         self.options = { }
  1162.         self.changed = set()
  1163.         self.conflicts = set()
  1164.         self.ppd = None
  1165.         self.ppds_lock = thread.allocate_lock()
  1166.         self.devices_lock = thread.allocate_lock()
  1167.         self.smb_lock = thread.allocate_lock()
  1168.         self.ipp_lock = thread.allocate_lock()
  1169.         self.drivers_lock = thread.allocate_lock()
  1170.         if not config.DOWNLOADABLE_DRIVER_SUPPORT:
  1171.             self.rbtnNPDownloadableDriverSearch.setEnabled(False)
  1172.             self.downloadableDriverSearchFrame.hide()
  1173.         
  1174.         self.btnSMBBrowse.hide()
  1175.         self.btnSMBVerify.hide()
  1176.         self.btnIPPFindQueue.hide()
  1177.         self.btnIPPVerify.hide()
  1178.         self.btnNPTLpdProbe.hide()
  1179.  
  1180.     
  1181.     def option_changed(self, option):
  1182.         if option.is_changed():
  1183.             self.changed.add(option)
  1184.         else:
  1185.             self.changed.discard(option)
  1186.         if option.conflicts:
  1187.             self.conflicts.add(option)
  1188.         else:
  1189.             self.conflicts.discard(option)
  1190.         self.setDataButtonState()
  1191.  
  1192.     
  1193.     def setDataButtonState(self):
  1194.         self.btnNPForward.setEnabled(not bool(self.conflicts))
  1195.  
  1196.     
  1197.     def init(self, dialog_mode):
  1198.         self.dialog_mode = dialog_mode
  1199.         self.options = { }
  1200.         self.changed = set()
  1201.         self.conflicts = set()
  1202.         if self.dialog_mode == 'printer':
  1203.             self.setWindowTitle(_('New Printer'))
  1204.             self.ntbkNewPrinter.setCurrentIndex(self.ntbkNewPrinterPages['device'])
  1205.             self.fillDeviceTab()
  1206.             self.on_rbtnNPFoomatic_toggled()
  1207.             self.new_printer_PPDs_loaded = False
  1208.             self.queryPPDs()
  1209.         elif self.dialog_mode == 'class':
  1210.             self.setWindowTitle(_('New Class'))
  1211.             self.fillNewClassMembers()
  1212.             self.ntbkNewPrinter.setCurrentIndex(self.ntbkNewPrinterPages['name'])
  1213.         elif self.dialog_mode == 'device':
  1214.             self.setWindowTitle(_('Change Device URI'))
  1215.             self.ntbkNewPrinter.setCurrentIndex(self.ntbkNewPrinterPages['device'])
  1216.             self.queryDevices()
  1217.             self.loadPPDs()
  1218.             self.fillDeviceTab(self.mainapp.printer.device_uri)
  1219.             self.new_printer_PPDs_loaded = False
  1220.             self.queryPPDs()
  1221.         elif self.dialog_mode == 'ppd':
  1222.             self.setWindowTitle(_('Change Driver'))
  1223.             self.ntbkNewPrinter.setCurrentIndex(2)
  1224.             self.on_rbtnNPFoomatic_toggled()
  1225.             self.auto_model = ''
  1226.             ppd = self.mainapp.ppd
  1227.             if ppd:
  1228.                 attr = ppd.findAttr('Manufacturer')
  1229.                 if attr:
  1230.                     self.auto_make = attr.value
  1231.                 else:
  1232.                     self.auto_make = ''
  1233.                 attr = ppd.findAttr('ModelName')
  1234.                 if not attr:
  1235.                     attr = ppd.findAttr('ShortNickName')
  1236.                 
  1237.                 if not attr:
  1238.                     attr = ppd.findAttr('NickName')
  1239.                 
  1240.                 if attr:
  1241.                     pass
  1242.                 None if attr.value.startswith(self.auto_make) else None<EXCEPTION MATCH>IndexError
  1243.                 self.auto_model = ''
  1244.             else:
  1245.                 self.auto_make = 'Raw'
  1246.                 self.auto_model = 'Queue'
  1247.             self.loadPPDs()
  1248.             self.fillMakeList()
  1249.         
  1250.         if self.dialog_mode in ('printer', 'class'):
  1251.             self.entNPName.setText(self.mainapp.makeNameUnique(self.dialog_mode))
  1252.             for widget in [
  1253.                 self.entNPLocation,
  1254.                 self.entNPDescription]:
  1255.                 widget.setText('')
  1256.             
  1257.             
  1258.             try:
  1259.                 p = os.popen('/bin/hostname', 'r')
  1260.                 hostname = p.read().strip()
  1261.                 p.close()
  1262.                 self.entNPLocation.setText(hostname)
  1263.             nonfatalException()
  1264.  
  1265.         
  1266.         self.entNPTDirectJetPort.setText('9100')
  1267.         self.setNPButtons()
  1268.         self.exec_()
  1269.  
  1270.     
  1271.     def queryPPDs(self):
  1272.         debugprint('queryPPDs')
  1273.         if not self.ppds_lock.acquire(0):
  1274.             debugprint('queryPPDs: in progress')
  1275.             return None
  1276.         
  1277.         debugprint('Lock acquired for PPDs thread')
  1278.         thread.start_new_thread(self.getPPDs_thread, (self.language[0],))
  1279.         debugprint('PPDs thread started')
  1280.  
  1281.     
  1282.     def getPPDs_thread(self, language):
  1283.         
  1284.         try:
  1285.             debugprint('Connecting (PPDs)')
  1286.             cups.setServer(self.mainapp.connect_server)
  1287.             cups.setUser(self.mainapp.connect_user)
  1288.             cups.setPasswordCB(self.mainapp.cupsPasswdCallback)
  1289.             c = cups.Connection()
  1290.             debugprint('Fetching PPDs')
  1291.             ppds_dict = c.getPPDs()
  1292.             self.ppds_result = cupshelpers.ppds.PPDs(ppds_dict, language = language)
  1293.             debugprint('Closing connection (PPDs)')
  1294.             del c
  1295.         except cups.IPPError:
  1296.             (e, msg) = None
  1297.             self.ppds_result = cups.IPPError(e, msg)
  1298.         except:
  1299.             nonfatalException()
  1300.             self.ppds_result = { }
  1301.  
  1302.         debugprint('Releasing PPDs lock')
  1303.         self.ppds_lock.release()
  1304.  
  1305.     
  1306.     def fetchPPDs(self, parent = None):
  1307.         debugprint('fetchPPDs')
  1308.         self.queryPPDs()
  1309.         time.sleep(0.1)
  1310.         waiting = False
  1311.         while self.ppds_lock.locked():
  1312.             if not waiting:
  1313.                 waiting = True
  1314.                 self.WaitWindow.setText('<b>' + _('Searching') + '</b><br /><br />' + _('Searching for drivers'))
  1315.                 self.WaitWindow.show()
  1316.             
  1317.             QApplication.processEvents()
  1318.             time.sleep(0.1)
  1319.         if waiting:
  1320.             self.WaitWindow.hide()
  1321.         
  1322.         debugprint('Got PPDs')
  1323.         result = self.ppds_result
  1324.         if isinstance(result, cups.IPPError):
  1325.             raise result
  1326.         
  1327.         return result
  1328.  
  1329.     
  1330.     def loadPPDs(self, parent = None):
  1331.         
  1332.         try:
  1333.             return self.ppds
  1334.         except:
  1335.             self.ppds = self.fetchPPDs(parent = parent)
  1336.             return self.ppds
  1337.  
  1338.  
  1339.     
  1340.     def dropPPDs(self):
  1341.         
  1342.         try:
  1343.             del self.ppds
  1344.         except:
  1345.             pass
  1346.  
  1347.  
  1348.     
  1349.     def fillNewClassMembers(self):
  1350.         self.tvNCMembers.clear()
  1351.         self.tvNCNotMembers.clear()
  1352.         for printer in self.mainapp.printers.itervalues():
  1353.             self.tvNCNotMembers.addItem(printer.name)
  1354.         
  1355.  
  1356.     
  1357.     def on_btnNCAddMember_clicked(self):
  1358.         self.mainapp.moveClassMembers(self.tvNCNotMembers, self.tvNCMembers)
  1359.         self.btnNPApply.setEnabled(bool(self.mainapp.getCurrentClassMembers(self.tvNCMembers)))
  1360.  
  1361.     on_btnNCAddMember_clicked = pyqtSignature('')(on_btnNCAddMember_clicked)
  1362.     
  1363.     def on_btnNCDelMember_clicked(self):
  1364.         self.mainapp.moveClassMembers(self.tvNCMembers, self.tvNCNotMembers)
  1365.         self.btnNPApply.setEnabled(bool(self.mainapp.getCurrentClassMembers(self.tvNCMembers)))
  1366.  
  1367.     on_btnNCDelMember_clicked = pyqtSignature('')(on_btnNCDelMember_clicked)
  1368.     
  1369.     def on_btnNPBack_clicked(self):
  1370.         self.nextNPTab(-1)
  1371.  
  1372.     on_btnNPBack_clicked = pyqtSignature('')(on_btnNPBack_clicked)
  1373.     
  1374.     def on_btnNPForward_clicked(self):
  1375.         self.nextNPTab()
  1376.  
  1377.     on_btnNPForward_clicked = pyqtSignature('')(on_btnNPForward_clicked)
  1378.     
  1379.     def nextNPTab(self, step = 1):
  1380.         page_nr = self.ntbkNewPrinter.currentIndex()
  1381.         if self.dialog_mode == 'class':
  1382.             order = [
  1383.                 self.ntbkNewPrinterPages['name'],
  1384.                 self.ntbkNewPrinterPages['class-members']]
  1385.         elif self.dialog_mode == 'printer':
  1386.             if page_nr == 1:
  1387.                 name = 'printer'
  1388.                 
  1389.                 try:
  1390.                     if self.device.id:
  1391.                         name = self.device.id_dict['MDL']
  1392.                     
  1393.                     name = self.mainapp.makeNameUnique(name)
  1394.                     self.entNPName.setText(name)
  1395.                 except:
  1396.                     nonfatalException()
  1397.  
  1398.                 (self.auto_make, self.auto_model) = (None, None)
  1399.                 self.device.uri = self.getDeviceURI()
  1400.                 if self.device.type in ('socket', 'lpd', 'ipp', 'bluetooth'):
  1401.                     host = self.getNetworkPrinterMakeModel(self.device)
  1402.                     faxuri = None
  1403.                     if host:
  1404.                         faxuri = self.get_hplip_uri_for_network_printer(host, 'fax')
  1405.                     
  1406.                     if faxuri:
  1407.                         dialog = gtk.Dialog(self.device.info, self.NewPrinterWindow, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (_('Printer'), 1, _('Fax'), 2))
  1408.                         label = gtk.Label(_('This printer supports both printing and sending faxes.  Which functionality should be used for this queue?'))
  1409.                         dialog.vbox.pack_start(label, True, True, 0)
  1410.                         label.show()
  1411.                         queue_type = dialog.run()
  1412.                         dialog.destroy()
  1413.                         if queue_type == 2:
  1414.                             self.device.id_dict = self.get_hpfax_device_id(faxuri)
  1415.                             self.device.uri = faxuri
  1416.                             self.auto_make = self.device.id_dict['MFG']
  1417.                             self.auto_model = self.device.id_dict['MDL']
  1418.                             self.device.id = 'MFG:' + self.auto_make + ';MDL:' + self.auto_model + ';DES:' + self.device.id_dict['DES'] + ';'
  1419.                         
  1420.                     
  1421.                 
  1422.                 uri = self.device.uri
  1423.                 if uri and uri.startswith('smb://'):
  1424.                     uri = SMBURI(uri = uri[6:]).sanitize_uri()
  1425.                 
  1426.                 self.remotecupsqueue = None
  1427.                 res = re.search('ipp://(\\S+(:\\d+|))/printers/(\\S+)', uri)
  1428.                 if res:
  1429.                     resg = res.groups()
  1430.                     
  1431.                     try:
  1432.                         conn = httplib.HTTPConnection(resg[0])
  1433.                         conn.request('GET', '/printers/%s.ppd' % resg[2])
  1434.                         resp = conn.getresponse()
  1435.                         if resp.status == 200:
  1436.                             self.remotecupsqueue = resg[2]
  1437.                     except:
  1438.                         debugprint('exception in getting remotecupsqueue')
  1439.  
  1440.                     oldserver = cups.getServer()
  1441.                     oldport = cups.getPort()
  1442.                     
  1443.                     try:
  1444.                         cups.setServer(resg[0])
  1445.                         if len(resg[1]) > 0:
  1446.                             cups.setPort(int(resg[1]))
  1447.                         else:
  1448.                             cups.setPort(631)
  1449.                         c = cups.Connection()
  1450.                         r = [
  1451.                             'printer-info',
  1452.                             'printer-location']
  1453.                         attrs = c.getPrinterAttributes(uri = uri, requested_attributes = r)
  1454.                         info = attrs.get('printer-info', '')
  1455.                         location = attrs.get('printer-location', '')
  1456.                         if len(info) > 0:
  1457.                             self.entNPDescription.setText(info)
  1458.                         
  1459.                         if len(location) > 0:
  1460.                             self.entNPLocation.setText(location)
  1461.                     except:
  1462.                         nonfatalException()
  1463.  
  1464.                     cups.setServer(oldserver)
  1465.                     cups.setPort(oldport)
  1466.                 
  1467.                 if not (self.remotecupsqueue) and not (self.new_printer_PPDs_loaded):
  1468.                     
  1469.                     try:
  1470.                         self.loadPPDs(self)
  1471.                     except cups.IPPError:
  1472.                         (e, msg) = None
  1473.                         self.show_IPP_Error(e, msg)
  1474.                         return None
  1475.                     except:
  1476.                         self.ready(self)
  1477.                         return None
  1478.  
  1479.                     self.new_printer_PPDs_loaded = True
  1480.                 
  1481.                 ppdname = None
  1482.                 
  1483.                 try:
  1484.                     if self.remotecupsqueue:
  1485.                         ppdname = 'raw'
  1486.                         self.ppd = ppdname
  1487.                         name = self.remotecupsqueue
  1488.                         name = self.mainapp.makeNameUnique(name)
  1489.                         self.entNPName.setText(name)
  1490.                     elif self.device.id:
  1491.                         id_dict = self.device.id_dict
  1492.                         (status, ppdname) = self.ppds.getPPDNameFromDeviceID(id_dict['MFG'], id_dict['MDL'], id_dict['DES'], id_dict['CMD'], self.device.uri)
  1493.                     else:
  1494.                         (status, ppdname) = self.ppds.getPPDNameFromDeviceID('Generic', 'Printer', 'Generic Printer', [], self.device.uri)
  1495.                     if ppdname and not (self.remotecupsqueue):
  1496.                         ppddict = self.ppds.getInfoFromPPDName(ppdname)
  1497.                         make_model = ppddict['ppd-make-and-model']
  1498.                         (make, model) = cupshelpers.ppds.ppdMakeModelSplit(make_model)
  1499.                         self.auto_make = make
  1500.                         self.auto_model = model
  1501.                 except:
  1502.                     nonfatalException()
  1503.  
  1504.                 if not self.remotecupsqueue:
  1505.                     self.fillMakeList()
  1506.                 
  1507.             elif page_nr == 3:
  1508.                 if not self.device.id:
  1509.                     
  1510.                     try:
  1511.                         items = self.tvNPModels.selectedItems()
  1512.                         name = unicode(items[0].text())
  1513.                         name = self.mainapp.makeNameUnique(name)
  1514.                         self.entNPName.setText(name)
  1515.                     nonfatalException()
  1516.  
  1517.                 
  1518.             
  1519.             if self.remotecupsqueue:
  1520.                 order = [
  1521.                     1,
  1522.                     0]
  1523.             elif self.rbtnNPFoomatic.isChecked():
  1524.                 order = [
  1525.                     1,
  1526.                     2,
  1527.                     3,
  1528.                     6,
  1529.                     0]
  1530.             elif self.rbtnNPPPD.isChecked():
  1531.                 order = [
  1532.                     1,
  1533.                     2,
  1534.                     6,
  1535.                     0]
  1536.             else:
  1537.                 order = [
  1538.                     1,
  1539.                     2,
  1540.                     7,
  1541.                     6,
  1542.                     0]
  1543.         elif self.dialog_mode == 'device':
  1544.             order = [
  1545.                 1]
  1546.         elif self.dialog_mode == 'ppd':
  1547.             self.rbtnChangePPDasIs.setChecked(True)
  1548.             if self.rbtnNPFoomatic.isChecked():
  1549.                 order = [
  1550.                     2,
  1551.                     3,
  1552.                     5,
  1553.                     6]
  1554.             elif self.rbtnNPPPD.isChecked():
  1555.                 order = [
  1556.                     2,
  1557.                     5,
  1558.                     6]
  1559.             else:
  1560.                 order = [
  1561.                     2,
  1562.                     7,
  1563.                     5,
  1564.                     6]
  1565.         
  1566.         next_page_nr = order[order.index(page_nr) + step]
  1567.         if next_page_nr == 6 and step > 0:
  1568.             self.ppd = self.getNPPPD()
  1569.             next_page_nr = order[order.index(next_page_nr) + 1]
  1570.         
  1571.         self.installable_options = False
  1572.         if next_page_nr == 6 and not (self.installable_options) and step < 0:
  1573.             next_page_nr = order[order.index(next_page_nr) - 1]
  1574.         
  1575.         if next_page_nr == 7:
  1576.             if self.drivers_lock.locked():
  1577.                 self.lblWait.set_markup('<span weight="bold" size="larger">' + _('Searching') + '</span>\n\n' + _('Searching for drivers'))
  1578.                 self.WaitWindow.set_transient_for(self.NewPrinterWindow)
  1579.                 self.WaitWindow.show()
  1580.                 self.busy(self)
  1581.                 while self.drivers_lock.locked():
  1582.                     while gtk.events_pending():
  1583.                         gtk.main_iteration()
  1584.                     time.sleep(0.1)
  1585.                 self.ready(self.NewPrinterWindow)
  1586.                 self.WaitWindow.hide()
  1587.             
  1588.             self.fillDownloadableDrivers()
  1589.         
  1590.         self.ntbkNewPrinter.setCurrentIndex(next_page_nr)
  1591.         self.setNPButtons()
  1592.  
  1593.     
  1594.     def setNPButtons(self):
  1595.         nr = self.ntbkNewPrinter.currentIndex()
  1596.         if self.dialog_mode == 'device':
  1597.             self.btnNPBack.hide()
  1598.             self.btnNPForward.hide()
  1599.             self.btnNPApply.show()
  1600.             uri = self.getDeviceURI()
  1601.             self.btnNPApply.setEnabled(validDeviceURI(uri))
  1602.             return None
  1603.         
  1604.         if self.dialog_mode == 'ppd':
  1605.             if nr == 5:
  1606.                 if not self.installable_options:
  1607.                     debugprint('No installable options')
  1608.                     self.btnNPForward.hide()
  1609.                     self.btnNPApply.show()
  1610.                 else:
  1611.                     self.btnNPForward.show()
  1612.                     self.btnNPApply.hide()
  1613.                 return None
  1614.             elif nr == 6:
  1615.                 self.btnNPForward.hide()
  1616.                 self.btnNPApply.show()
  1617.                 return None
  1618.             else:
  1619.                 self.btnNPForward.show()
  1620.                 self.btnNPApply.hide()
  1621.             if nr == 2:
  1622.                 self.btnNPBack.hide()
  1623.                 self.btnNPForward.show()
  1624.                 downloadable_selected = False
  1625.                 if self.rbtnNPDownloadableDriverSearch.isChecked():
  1626.                     combobox = self.cmbNPDownloadableDriverFoundPrinters
  1627.                     iter = combobox.get_active_iter()
  1628.                     if iter and combobox.get_model().get_value(iter, 1):
  1629.                         downloadable_selected = True
  1630.                     
  1631.                 
  1632.                 if not self.rbtnNPFoomatic.isChecked() and self.filechooserPPD.get_filename():
  1633.                     pass
  1634.                 self.btnNPForward.setEnabled(bool(downloadable_selected))
  1635.                 return None
  1636.             else:
  1637.                 self.btnNPBack.show()
  1638.         
  1639.         if nr == 1:
  1640.             valid = False
  1641.             
  1642.             try:
  1643.                 uri = self.getDeviceURI()
  1644.                 valid = validDeviceURI(uri)
  1645.             except:
  1646.                 pass
  1647.  
  1648.             self.btnNPForward.setEnabled(valid)
  1649.             self.btnNPBack.hide()
  1650.         else:
  1651.             self.btnNPBack.show()
  1652.         self.btnNPForward.show()
  1653.         self.btnNPApply.hide()
  1654.         if nr == 0:
  1655.             self.btnNPBack.show()
  1656.             if self.dialog_mode == 'class':
  1657.                 self.btnNPForward.setEnabled(True)
  1658.             
  1659.             if self.dialog_mode == 'printer':
  1660.                 self.btnNPForward.hide()
  1661.                 self.btnNPApply.show()
  1662.                 self.btnNPApply.setEnabled(self.mainapp.checkNPName(unicode(self.entNPName.text())))
  1663.             
  1664.         
  1665.         if nr == 2:
  1666.             downloadable_selected = False
  1667.             if self.rbtnNPDownloadableDriverSearch.isChecked():
  1668.                 combobox = self.cmbNPDownloadableDriverFoundPrinters
  1669.                 iter = combobox.get_active_iter()
  1670.                 if iter and combobox.get_model().get_value(iter, 1):
  1671.                     downloadable_selected = True
  1672.                 
  1673.             
  1674.             if not self.rbtnNPFoomatic.isChecked() and self.filechooserPPD.get_filename():
  1675.                 pass
  1676.             self.btnNPForward.setEnabled(bool(downloadable_selected))
  1677.         
  1678.         if nr == 3:
  1679.             iter = self.tvNPDrivers.currentItem()
  1680.             self.btnNPForward.setEnabled(bool(iter))
  1681.         
  1682.         if nr == 4:
  1683.             self.btnNPForward.hide()
  1684.             self.btnNPApply.show()
  1685.             self.btnNPApply.setEnabled(self.tvNCMembers.count() > 0)
  1686.         
  1687.         if nr == 7:
  1688.             if self.ntbkNPDownloadableDriverProperties.get_current_page() == 1:
  1689.                 accepted = self.rbtnNPDownloadLicenseYes.get_active()
  1690.             else:
  1691.                 treeview = self.tvNPDownloadableDrivers
  1692.                 (model, iter) = treeview.get_selection().get_selected()
  1693.                 accepted = iter != None
  1694.             self.btnNPForward.set_sensitive(accepted)
  1695.         
  1696.  
  1697.     
  1698.     def getDevices_thread(self):
  1699.         
  1700.         try:
  1701.             debugprint('Connecting (devices)')
  1702.             cups.setServer(self.mainapp.connect_server)
  1703.             cups.setUser('jr')
  1704.             cups.setPasswordCB(self.mainapp.cupsPasswdCallback)
  1705.             c = cups.Connection()
  1706.             debugprint('Fetching devices')
  1707.             self.devices_result = cupshelpers.getDevices(c)
  1708.         except cups.IPPError:
  1709.             (e, msg) = None
  1710.             self.devices_result = cups.IPPError(e, msg)
  1711.         except:
  1712.             debugprint('Exception in getDevices_thread')
  1713.             self.devices_result = { }
  1714.  
  1715.         
  1716.         try:
  1717.             debugprint('Closing connection (devices)')
  1718.             del c
  1719.         except:
  1720.             pass
  1721.  
  1722.         debugprint('Releasing devices lock')
  1723.         self.devices_lock.release()
  1724.  
  1725.     
  1726.     def queryDevices(self):
  1727.         if not self.devices_lock.acquire(0):
  1728.             debugprint('queryDevices: in progress')
  1729.             return None
  1730.         
  1731.         debugprint('Lock acquired for devices thread')
  1732.         thread.start_new_thread(self.getDevices_thread, ())
  1733.         debugprint('Devices thread started')
  1734.  
  1735.     
  1736.     def fetchDevices(self, parent = None):
  1737.         debugprint('fetchDevices')
  1738.         self.queryDevices()
  1739.         time.sleep(0.1)
  1740.         waiting = False
  1741.         while self.devices_lock.locked():
  1742.             if not waiting:
  1743.                 waiting = True
  1744.                 self.WaitWindow.setText('<b>' + _('Searching') + '</b><br/><br/>' + _('Searching for printers'))
  1745.                 self.WaitWindow.show()
  1746.             
  1747.             QApplication.processEvents()
  1748.             time.sleep(0.1)
  1749.         if waiting:
  1750.             self.WaitWindow.hide()
  1751.         
  1752.         debugprint('Got devices')
  1753.         result = self.devices_result
  1754.         if isinstance(result, cups.IPPError):
  1755.             raise result
  1756.         
  1757.         return result
  1758.  
  1759.     
  1760.     def get_hpfax_device_id(self, faxuri):
  1761.         os.environ['URI'] = faxuri
  1762.         cmd = 'LC_ALL=C DISPLAY= hp-info -d "${URI}"'
  1763.         debugprint(faxuri + ': ' + cmd)
  1764.         
  1765.         try:
  1766.             p = subprocess.Popen(cmd, shell = True, stdin = file('/dev/null'), stdout = subprocess.PIPE, stderr = subprocess.PIPE)
  1767.             (stdout, stderr) = p.communicate()
  1768.         except:
  1769.             return None
  1770.  
  1771.         for line in stdout.split('\n'):
  1772.             if line.find('fax-type') == -1:
  1773.                 continue
  1774.             
  1775.             faxtype = -1
  1776.             res = re.search('(\\d+)', line)
  1777.             if res:
  1778.                 resg = res.groups()
  1779.                 faxtype = resg[0]
  1780.             
  1781.             if faxtype >= 0:
  1782.                 break
  1783.                 continue
  1784.         
  1785.         if faxtype < 0:
  1786.             return None
  1787.         elif faxtype == 4:
  1788.             return cupshelpers.parseDeviceID('MFG:HP;MDL:Fax 2;DES:HP Fax 2;')
  1789.         else:
  1790.             return cupshelpers.parseDeviceID('MFG:HP;MDL:Fax;DES:HP Fax;')
  1791.  
  1792.     
  1793.     def get_hplip_uri_for_network_printer(self, host, mode):
  1794.         os.environ['HOST'] = host
  1795.         if mode == 'print':
  1796.             mod = '-c'
  1797.         elif mode == 'fax':
  1798.             mod = '-f'
  1799.         else:
  1800.             mod = '-c'
  1801.         cmd = 'hp-makeuri ' + mod + ' "${HOST}"'
  1802.         debugprint(host + ': ' + cmd)
  1803.         uri = None
  1804.         
  1805.         try:
  1806.             p = subprocess.Popen(cmd, shell = True, stdin = file('/dev/null'), stdout = subprocess.PIPE, stderr = subprocess.PIPE)
  1807.             (stdout, stderr) = p.communicate()
  1808.         except:
  1809.             return None
  1810.  
  1811.         uri = stdout.strip()
  1812.         return uri
  1813.  
  1814.     
  1815.     def getNetworkPrinterMakeModel(self, device):
  1816.         host = None
  1817.         s = device.uri.find('://')
  1818.         if s != -1:
  1819.             s += 3
  1820.             e = device.uri[s:].find(':')
  1821.             if e == -1:
  1822.                 e = device.uri[s:].find('/')
  1823.             
  1824.             if e == -1:
  1825.                 e = device.uri[s:].find('?')
  1826.             
  1827.             if e == -1:
  1828.                 e = len(device.uri)
  1829.             
  1830.             host = device.uri[s:s + e]
  1831.         
  1832.         if host:
  1833.             os.environ['HOST'] = host
  1834.             cmd = '/usr/lib/cups/backend/snmp "${HOST}"'
  1835.             debugprint(host + ': ' + cmd)
  1836.             stdout = None
  1837.             
  1838.             try:
  1839.                 p = subprocess.Popen(cmd, shell = True, stdin = file('/dev/null'), stdout = subprocess.PIPE, stderr = subprocess.PIPE)
  1840.                 (stdout, stderr) = p.communicate()
  1841.             except:
  1842.                 pass
  1843.  
  1844.             if stdout != None:
  1845.                 mm = re.sub('^\\s*\\S+\\s+\\S+\\s+"', '', stdout)
  1846.                 mm = re.sub('"\\s+.*$', '', mm)
  1847.                 if mm and mm != '':
  1848.                     device.make_and_model = mm
  1849.                 
  1850.             
  1851.         
  1852.         make_and_model = None
  1853.         if len(device.make_and_model) > 7:
  1854.             make_and_model = device.make_and_model
  1855.         elif len(device.info) > 7:
  1856.             make_and_model = device.info
  1857.             make_and_model = re.sub('\\s*(\\(|\\d+\\.\\d+\\.\\d+\\.\\d+).*$', '', make_and_model)
  1858.         
  1859.         if make_and_model and not (device.id):
  1860.             mk = None
  1861.             md = None
  1862.             (mk, md) = cupshelpers.ppds.ppdMakeModelSplit(make_and_model)
  1863.             device.id = 'MFG:' + mk + ';MDL:' + md + ';DES:' + mk + ' ' + md + ';'
  1864.             device.id_dict = cupshelpers.parseDeviceID(device.id)
  1865.         
  1866.         if host:
  1867.             hplipuri = self.get_hplip_uri_for_network_printer(host, 'print')
  1868.             if hplipuri:
  1869.                 device.uri = hplipuri
  1870.                 s = hplipuri.find('/usb/')
  1871.                 if s == -1:
  1872.                     s = hplipuri.find('/par/')
  1873.                 
  1874.                 if s == -1:
  1875.                     s = hplipuri.find('/net/')
  1876.                 
  1877.                 if s != -1:
  1878.                     s += 5
  1879.                     e = hplipuri[s:].find('?')
  1880.                     if e == -1:
  1881.                         e = len(hplipuri)
  1882.                     
  1883.                     mdl = hplipuri[s:s + e].replace('_', ' ')
  1884.                     if mdl.startswith('hp ') or mdl.startswith('HP '):
  1885.                         mdl = mdl[3:]
  1886.                         device.make_and_model = 'HP ' + mdl
  1887.                         device.id = 'MFG:HP;MDL:' + mdl + ';DES:HP ' + mdl + ';'
  1888.                         device.id_dict = cupshelpers.parseDeviceID(device.id)
  1889.                     
  1890.                 
  1891.             
  1892.         
  1893.         return host
  1894.  
  1895.     
  1896.     def fillDeviceTab(self, current_uri = None, query = True):
  1897.         if query:
  1898.             
  1899.             try:
  1900.                 devices = self.fetchDevices()
  1901.             except cups.IPPError:
  1902.                 (e, msg) = None
  1903.                 self.show_IPP_Error(e, msg)
  1904.                 devices = { }
  1905.             except:
  1906.                 nonfatalException()
  1907.                 devices = { }
  1908.  
  1909.             if current_uri:
  1910.                 if devices.has_key(current_uri):
  1911.                     current = devices.pop(current_uri)
  1912.                 else:
  1913.                     current = cupshelpers.Device(current_uri)
  1914.                     current.info = 'Current device'
  1915.             
  1916.             self.devices = devices.values()
  1917.         
  1918.         for device in self.devices:
  1919.             if device.type == 'usb':
  1920.                 ser = None
  1921.                 s = device.uri.find('?serial=')
  1922.                 if s != -1:
  1923.                     s += 8
  1924.                     e = device.uri[s:].find('?')
  1925.                     if e == -1:
  1926.                         e = len(device.uri)
  1927.                     
  1928.                     ser = device.uri[s:s + e]
  1929.                 
  1930.                 mod = None
  1931.                 s = device.uri[6:].find('/')
  1932.                 if s != -1:
  1933.                     s += 7
  1934.                     e = device.uri[s:].find('?')
  1935.                     if e == -1:
  1936.                         e = len(device.uri)
  1937.                     
  1938.                     mod = device.uri[s:s + e].lower().replace('%20', '_')
  1939.                     if mod.startswith('hp_'):
  1940.                         mod = mod[3:]
  1941.                     
  1942.                 
  1943.                 matchfound = 0
  1944.                 for hpdevice in self.devices:
  1945.                     hpser = None
  1946.                     hpmod = None
  1947.                     uri = hpdevice.uri
  1948.                     if not uri.startswith('hp:'):
  1949.                         continue
  1950.                     
  1951.                     if ser:
  1952.                         s = uri.find('?serial=')
  1953.                         if s != -1:
  1954.                             s += 8
  1955.                             e = uri[s:].find('?')
  1956.                             if e == -1:
  1957.                                 e = len(uri)
  1958.                             
  1959.                             hpser = uri[s:s + e]
  1960.                             if hpser != ser:
  1961.                                 continue
  1962.                             
  1963.                             matchfound = 1
  1964.                         
  1965.                     
  1966.                     if mod:
  1967.                         if ser:
  1968.                             pass
  1969.                         if not hpser:
  1970.                             s = uri.find('/usb/')
  1971.                             if s != -1:
  1972.                                 s += 5
  1973.                                 e = uri[s:].find('?')
  1974.                                 if e == -1:
  1975.                                     e = len(uri)
  1976.                                 
  1977.                                 hpmod = uri[s:s + e].lower()
  1978.                                 if hpmod.startswith('hp_'):
  1979.                                     hpmod = hpmod[3:]
  1980.                                 
  1981.                                 if hpmod != mod:
  1982.                                     continue
  1983.                                 
  1984.                                 matchfound = 1
  1985.                             
  1986.                         
  1987.                     if matchfound == 1:
  1988.                         break
  1989.                         continue
  1990.                 
  1991.                 if matchfound == 1:
  1992.                     device.uri = 'delete'
  1993.                 
  1994.             
  1995.             if device.type == 'hal':
  1996.                 if device.uri.startswith('hal:///org/freedesktop/Hal/devices/usb_device'):
  1997.                     device.uri = 'delete'
  1998.                 
  1999.             
  2000.             if device.type == 'socket':
  2001.                 device.uri = device.uri.replace(':9100', '')
  2002.             
  2003.             
  2004.             try:
  2005.                 if False and device.type in ('socket', 'lpd', 'ipp', 'bluetooth'):
  2006.                     host = self.getNetworkPrinterMakeModel(device)
  2007.                     faxuri = None
  2008.                     if host:
  2009.                         faxuri = self.get_hplip_uri_for_network_printer(host, 'fax')
  2010.                     
  2011.                     if faxuri:
  2012.                         self.devices.append(cupshelpers.Device(faxuri, **{
  2013.                             'device-class': 'direct',
  2014.                             'device-info': device.info + ' HP Fax HPLIP',
  2015.                             'device-device-make-and-model': 'HP Fax',
  2016.                             'device-id': 'MFG:HP;MDL:Fax;DES:HP Fax;' }))
  2017.                     
  2018.                     if device.uri.startswith('hp:'):
  2019.                         device.type = 'hp'
  2020.                         device.info += ' HPLIP'
  2021.                     
  2022.             continue
  2023.             nonfatalException()
  2024.             continue
  2025.  
  2026.         
  2027.         for i in range(len(self.devices)):
  2028.             for j in range(len(self.devices)):
  2029.                 if i == j:
  2030.                     continue
  2031.                 
  2032.                 device1 = self.devices[i]
  2033.                 device2 = self.devices[j]
  2034.                 if device1.uri == 'delete' or device2.uri == 'delete':
  2035.                     continue
  2036.                 
  2037.                 if device1.uri == device2.uri:
  2038.                     if not device1.id:
  2039.                         device1.uri = 'delete'
  2040.                     elif not device2.id:
  2041.                         device2.uri = 'delete'
  2042.                     elif len(device1.id) < len(device2.id):
  2043.                         device1.uri = 'delete'
  2044.                     else:
  2045.                         device2.uri = 'delete'
  2046.                 device1.id
  2047.             
  2048.         
  2049.         self.devices = filter((lambda x: x.uri not in ('hp:/no_device_found', 'hpfax:/no_device_found', 'hp', 'hpfax', 'hal', 'beh', 'scsi', 'http', 'delete')), self.devices)
  2050.         self.devices.sort()
  2051.         self.devices.append(cupshelpers.Device('', **{
  2052.             'device-info': _('Other') }))
  2053.         if current_uri:
  2054.             current.info += _(' (Current)')
  2055.             self.devices.insert(0, current)
  2056.             self.device = current
  2057.         
  2058.         self.tvNPDevices.clear()
  2059.         for device in self.devices:
  2060.             self.tvNPDevices.addItem(device.info)
  2061.         
  2062.         self.tvNPDevices.setCurrentRow(0)
  2063.         self.on_tvNPDevices_cursor_changed()
  2064.  
  2065.     
  2066.     def on_entNPTDevice_changed(self, entry):
  2067.         self.setNPButtons()
  2068.  
  2069.     
  2070.     def on_entSMBURI_changed(self, text):
  2071.         uri = unicode(text)
  2072.         (group, host, share, user, password) = SMBURI(uri = uri).separate()
  2073.         if user:
  2074.             self.entSMBUsername.setText(user)
  2075.         
  2076.         if password:
  2077.             self.entSMBPassword.setText(password)
  2078.         
  2079.         if user or password:
  2080.             uri = SMBURI(group = group, host = host, share = share).get_uri()
  2081.             self.entSMBURI.setText(uri)
  2082.             self.rbtnSMBAuthSet.setChecked(True)
  2083.         elif unicode(self.entSMBUsername.text()) == '':
  2084.             self.rbtnSMBAuthPrompt.setChecked(True)
  2085.         
  2086.         self.btnSMBVerify.setEnabled(bool(uri))
  2087.  
  2088.     
  2089.     def on_rbtnSMBAuthSet_toggled(self, ticked):
  2090.         self.tblSMBAuth.setEnabled(ticked)
  2091.  
  2092.     
  2093.     def on_entNPTIPPHostname_textChanged(self):
  2094.         valid = len(self.entNPTIPPHostname.text()) > 0
  2095.         self.btnIPPFindQueue.setEnabled(valid)
  2096.         self.update_IPP_URI_label()
  2097.  
  2098.     
  2099.     def update_IPP_URI_label(self):
  2100.         hostname = unicode(self.entNPTIPPHostname.text())
  2101.         queue = unicode(self.entNPTIPPQueuename.text())
  2102.         if len(hostname) > 0:
  2103.             pass
  2104.         valid = queue != '/printers/'
  2105.         if valid:
  2106.             uri = 'ipp://%s%s' % (hostname, queue)
  2107.             self.lblIPPURI.setText(uri)
  2108.             self.lblIPPURI.show()
  2109.             self.entNPTIPPQueuename.show()
  2110.         else:
  2111.             self.lblIPPURI.hide()
  2112.         self.btnIPPVerify.setEnabled(valid)
  2113.         self.setNPButtons()
  2114.  
  2115.     
  2116.     def on_btnIPPFindQueue_clicked(self):
  2117.         self.IPPBrowseBox.clear()
  2118.         host = str(self.entNPTIPPHostname.text())
  2119.         cups.setServer(host)
  2120.         printers = classes = { }
  2121.         
  2122.         try:
  2123.             c = cups.Connection()
  2124.             printers = c.getPrinters()
  2125.             classes = c.getClasses()
  2126.             del c
  2127.         except RuntimeError:
  2128.             pass
  2129.         except cups.IPP_Error:
  2130.             (e, msg) = None
  2131.  
  2132.         for printer, dict in printers.iteritems():
  2133.             self.IPPBrowseBox.addItem(printer)
  2134.         
  2135.         for pclass, dict in classes.iteritems():
  2136.             pass
  2137.         
  2138.         if len(printers) + len(classes) == 0:
  2139.             QMessageBox.information(self, _('No queues'), _('There are no queues available.'))
  2140.         
  2141.  
  2142.     on_btnIPPFindQueue_clicked = pyqtSignature('')(on_btnIPPFindQueue_clicked)
  2143.     
  2144.     def on_tvNPDevices_cursor_changed(self):
  2145.         device = self.devices[self.tvNPDevices.currentRow()]
  2146.         self.device = device
  2147.         self.lblNPDeviceDescription.setText('')
  2148.         page = self.new_printer_device_tabs.get(device.type, 1)
  2149.         self.ntbkNPType.setCurrentIndex(page)
  2150.         type = device.type
  2151.         url = device.uri.split(':', 1)[-1]
  2152.         if page == 0:
  2153.             if device.type == 'parallel':
  2154.                 text = _('A printer connected to the parallel port.')
  2155.             elif device.type == 'usb':
  2156.                 text = _('A printer connected to a USB port.')
  2157.             elif device.type == 'hp':
  2158.                 text = _('HPLIP software driving a printer, or the printer function of a multi-function device.')
  2159.             elif device.type == 'hpfax':
  2160.                 text = _('HPLIP software driving a fax machine, or the fax function of a multi-function device.')
  2161.             elif device.type == 'hal':
  2162.                 text = _('Local printer detected by the Hardware Abstraction Layer (HAL).')
  2163.             else:
  2164.                 text = device.uri
  2165.             self.lblNPDeviceDescription.setText(text)
  2166.         elif device.type == 'socket':
  2167.             if device.uri.startswith('socket'):
  2168.                 host = device.uri[9:]
  2169.                 i = host.find(':')
  2170.                 if i != -1:
  2171.                     port = int(host[i + 1:])
  2172.                     host = host[:i]
  2173.                 else:
  2174.                     port = 9100
  2175.                 self.entNPTDirectJetHostname.setText(host)
  2176.                 self.entNPTDirectJetPort.setText(str(port))
  2177.             
  2178.         elif device.type == 'serial':
  2179.             if not device.is_class:
  2180.                 options = device.uri.split('?')[1]
  2181.                 options = options.split('+')
  2182.                 option_dict = { }
  2183.                 for option in options:
  2184.                     (name, value) = option.split('=')
  2185.                     option_dict[name] = value
  2186.                 
  2187.                 for widget, name, optionvalues in ((self.cmbNPTSerialBaud, 'baud', None), (self.cmbNPTSerialBits, 'bits', None), (self.cmbNPTSerialParity, 'parity', [
  2188.                     'none',
  2189.                     'odd',
  2190.                     'even']), (self.cmbNPTSerialFlow, 'flow', [
  2191.                     'none',
  2192.                     'soft',
  2193.                     'hard',
  2194.                     'hard'])):
  2195.                     if option_dict.has_key(name):
  2196.                         if optionvalues is None:
  2197.                             model = widget.get_model()
  2198.                             iter = model.get_iter_first()
  2199.                             nr = 0
  2200.                             while iter:
  2201.                                 value = model.get(iter, 0)[0]
  2202.                                 if value == option_dict[name]:
  2203.                                     widget.set_active(nr)
  2204.                                     break
  2205.                                 
  2206.                                 iter = model.iter_next(iter)
  2207.                                 nr += 1
  2208.                         else:
  2209.                             nr = optionvalues.index(option_dict[name])
  2210.                             widget.set_active(nr + 1)
  2211.                     optionvalues is None
  2212.                     widget.set_active(0)
  2213.                 
  2214.             
  2215.         elif device.type in ('ipp', 'http'):
  2216.             if device.uri.startswith('ipp:') or device.uri.startswith('http:'):
  2217.                 match = re.match('(ipp|https?)://([^/]+)(.*)', device.uri)
  2218.                 if match:
  2219.                     server = match.group(2)
  2220.                     printer = match.group(3)
  2221.                 else:
  2222.                     server = ''
  2223.                     printer = ''
  2224.                 self.entNPTIPPHostname.setText(server)
  2225.                 self.entNPTIPPQueuename.setText(printer)
  2226.                 self.lblIPPURI.setText(device.uri)
  2227.                 self.lblIPPURI.show()
  2228.                 self.entNPTIPPQueuename.show()
  2229.             else:
  2230.                 self.entNPTIPPHostname.setText('')
  2231.                 self.entNPTIPPQueuename.setText('/printers/')
  2232.                 self.entNPTIPPQueuename.show()
  2233.                 self.lblIPPURI.hide()
  2234.         elif device.type == 'lpd':
  2235.             if device.uri.startswith('lpd'):
  2236.                 host = device.uri[6:]
  2237.                 i = host.find('/')
  2238.                 if i != -1:
  2239.                     printer = host[i + 1:]
  2240.                     host = host[:i]
  2241.                 else:
  2242.                     printer = ''
  2243.                 self.cmbentNPTLpdHost.addItem(host)
  2244.                 self.cmbentNPTLpdQueue.addItem(printer)
  2245.             
  2246.         elif device.uri == 'lpd':
  2247.             pass
  2248.         elif device.uri == 'smb':
  2249.             self.entSMBURI.setText('')
  2250.             self.btnSMBVerify.setEnabled(False)
  2251.         elif device.type == 'smb':
  2252.             self.entSMBUsername.setText('')
  2253.             self.entSMBPassword.setText('')
  2254.             self.entSMBURI.set_text(device.uri[6:])
  2255.             self.btnSMBVerify.setEnabled(True)
  2256.         else:
  2257.             self.entNPTDevice.setText(device.uri)
  2258.         self.setNPButtons()
  2259.  
  2260.     
  2261.     def getDeviceURI(self):
  2262.         type = self.device.type
  2263.         if type == 'socket':
  2264.             host = unicode(self.entNPTDirectJetHostname.text())
  2265.             port = unicode(self.entNPTDirectJetPort.text())
  2266.             device = 'socket://' + host
  2267.             if port:
  2268.                 device = device + ':' + port
  2269.             
  2270.         elif type in ('http', 'ipp'):
  2271.             if self.lblIPPURI.isVisible:
  2272.                 device = unicode(self.lblIPPURI.text())
  2273.             else:
  2274.                 device = 'ipp'
  2275.         elif type == 'lpd':
  2276.             host = unicode(self.cmbentNPTLpdHost.currentText())
  2277.             printer = unicode(self.cmbentNPTLpdQueue.currentText())
  2278.             device = 'lpd://' + host
  2279.             if printer:
  2280.                 device = device + '/' + printer
  2281.             
  2282.         elif type == 'parallel':
  2283.             device = self.device.uri
  2284.         elif type == 'scsi':
  2285.             device = ''
  2286.         elif type == 'serial':
  2287.             options = []
  2288.             for widget, name, optionvalues in ((self.cmbNPTSerialBaud, 'baud', None), (self.cmbNPTSerialBits, 'bits', None), (self.cmbNPTSerialParity, 'parity', ('none', 'odd', 'even')), (self.cmbNPTSerialFlow, 'flow', ('none', 'soft', 'hard', 'hard'))):
  2289.                 nr = widget.get_active()
  2290.                 if nr:
  2291.                     if optionvalues is not None:
  2292.                         option = optionvalues[nr - 1]
  2293.                     else:
  2294.                         option = widget.get_active_text()
  2295.                     options.append(name + '=' + option)
  2296.                     continue
  2297.             
  2298.             options = '+'.join(options)
  2299.             device = self.device.uri.split('?')[0]
  2300.             if options:
  2301.                 device = device + '?' + options
  2302.             
  2303.         elif type == 'smb':
  2304.             uri = unicode(self.entSMBURI.text())
  2305.             (group, host, share, u, p) = SMBURI(uri = uri).separate()
  2306.             user = ''
  2307.             password = ''
  2308.             if self.rbtnSMBAuthSet.isChecked():
  2309.                 user = unicode(self.entSMBUsername.text())
  2310.                 password = unicode(self.entSMBPassword.text())
  2311.             
  2312.             uri = SMBURI(group = group, host = host, share = share, user = user, password = password).get_uri()
  2313.             device = 'smb://' + uri
  2314.         elif not self.device.is_class:
  2315.             device = self.device.uri
  2316.         else:
  2317.             device = str(self.entNPTDevice.text())
  2318.         return device
  2319.         if nr == self.ntbkNewPrinterPages['device']:
  2320.             valid = False
  2321.             
  2322.             try:
  2323.                 uri = self.getDeviceURI()
  2324.                 valid = validDeviceURI(uri)
  2325.             except:
  2326.                 debugprint('exception in getDeviceURI()')
  2327.  
  2328.             self.btnNPForward.setEnabled(valid)
  2329.             self.btnNPBack.hide()
  2330.         else:
  2331.             self.btnNPBack.show()
  2332.         self.btnNPForward.show()
  2333.         self.btnNPApply.hide()
  2334.         if nr == self.ntbkNewPrinterPages['name']:
  2335.             self.btnNPBack.show()
  2336.             if self.dialog_mode == 'printer':
  2337.                 self.btnNPForward.hide()
  2338.                 self.btnNPApply.show()
  2339.                 self.btnNPApply.setEnabled(self.mainapp.checkNPName(self.entNPName.getText()))
  2340.             
  2341.         
  2342.         if nr == self.ntbkNewPrinterPages['make']:
  2343.             downloadable_selected = False
  2344.             if self.rbtnNPDownloadableDriverSearch.get_active():
  2345.                 combobox = self.cmbNPDownloadableDriverFoundPrinters
  2346.                 iter = combobox.get_active_iter()
  2347.                 if iter and combobox.get_model().get_value(iter, 1):
  2348.                     downloadable_selected = True
  2349.                 
  2350.             
  2351.             if not self.rbtnNPFoomatic.get_active() and self.filechooserPPD.get_filename():
  2352.                 pass
  2353.             self.btnNPForward.setEnabled(bool(downloadable_selected))
  2354.         
  2355.         if nr == self.ntbkNewPrinterPages['model']:
  2356.             (model, iter) = self.tvNPDrivers.get_selection().get_selected()
  2357.             self.btnNPForward.set_sensitive(bool(iter))
  2358.         
  2359.         if nr == self.ntbkNewPrinterPages['class-members']:
  2360.             self.btnNPForward.hide()
  2361.             self.btnNPApply.show()
  2362.             self.btnNPApply.setEnabled(bool(self.mainapp.getCurrentClassMembers(self.tvNCMembers)))
  2363.         
  2364.         if nr == self.ntbkNewPrinterPages['downloadable']:
  2365.             if self.ntbkNPDownloadableDriverProperties.get_current_page() == 1:
  2366.                 accepted = self.rbtnNPDownloadLicenseYes.get_active()
  2367.             else:
  2368.                 accepted = True
  2369.             self.btnNPForward.set_sensitive(accepted)
  2370.         
  2371.  
  2372.     
  2373.     def on_rbtnNPFoomatic_toggled(self):
  2374.         rbtn1 = self.rbtnNPFoomatic.isChecked()
  2375.         rbtn2 = self.rbtnNPPPD.isChecked()
  2376.         rbtn3 = self.rbtnNPDownloadableDriverSearch.isChecked()
  2377.         self.tvNPMakes.setEnabled(rbtn1)
  2378.         self.filechooserPPD.setEnabled(rbtn2)
  2379.         for widget in [
  2380.             self.entNPDownloadableDriverSearch,
  2381.             self.cmbNPDownloadableDriverFoundPrinters]:
  2382.             widget.setEnabled(rbtn3)
  2383.         
  2384.         if rbtn3:
  2385.             pass
  2386.         self.btnNPDownloadableDriverSearch.setEnabled(self.openprinting_query_handle == None)
  2387.         self.setNPButtons()
  2388.  
  2389.     
  2390.     def fillMakeList(self):
  2391.         makes = self.ppds.getMakes()
  2392.         self.tvNPMakes.clear()
  2393.         found = False
  2394.         index = 0
  2395.         for make in makes:
  2396.             self.tvNPMakes.addItem(make)
  2397.             index = index + 1
  2398.             if make == self.auto_make:
  2399.                 self.tvNPMakes.setCurrentRow(index - 1)
  2400.                 found = True
  2401.                 continue
  2402.         
  2403.         self.on_tvNPMakes_cursor_changed()
  2404.  
  2405.     
  2406.     def on_tvNPMakes_cursor_changed(self):
  2407.         items = self.tvNPMakes.selectedItems()
  2408.         if len(items) > 0:
  2409.             self.NPMake = unicode(items[0].text())
  2410.             self.fillModelList()
  2411.         
  2412.  
  2413.     
  2414.     def fillModelList(self):
  2415.         models = self.ppds.getModels(self.NPMake)
  2416.         self.tvNPModels.clear()
  2417.         selected = False
  2418.         index = 0
  2419.         selected = False
  2420.         for pmodel in models:
  2421.             self.tvNPModels.addItem(pmodel)
  2422.             if self.NPMake == self.auto_make and pmodel == self.auto_model:
  2423.                 self.tvNPModels.setCurrentRow(index)
  2424.                 selected = True
  2425.             
  2426.             index = index + 1
  2427.         
  2428.         if not selected:
  2429.             self.tvNPModels.setCurrentRow(0)
  2430.         
  2431.         self.on_tvNPModels_cursor_changed()
  2432.  
  2433.     
  2434.     def fillDriverList(self, pmake, pmodel):
  2435.         self.NPModel = pmodel
  2436.         self.tvNPDrivers.clear()
  2437.         ppds = self.ppds.getInfoFromModel(pmake, pmodel)
  2438.         self.NPDrivers = self.ppds.orderPPDNamesByPreference(ppds.keys())
  2439.         for i in range(len(self.NPDrivers)):
  2440.             ppd = ppds[self.NPDrivers[i]]
  2441.             driver = ppd['ppd-make-and-model']
  2442.             driver = driver.replace(' (recommended)', '')
  2443.             
  2444.             try:
  2445.                 lpostfix = ' [%s]' % ppd['ppd-natural-language']
  2446.                 driver += lpostfix
  2447.             except KeyError:
  2448.                 pass
  2449.  
  2450.             if i == 0:
  2451.                 self.tvNPDrivers.addItem(driver + _(' (recommended)'))
  2452.                 self.tvNPDrivers.setCurrentRow(0)
  2453.                 continue
  2454.             self.tvNPDrivers.addItem(driver)
  2455.         
  2456.  
  2457.     
  2458.     def on_tvNPModels_cursor_changed(self):
  2459.         items = self.tvNPModels.selectedItems()
  2460.         if len(items) > 0:
  2461.             pmodel = unicode(items[0].text())
  2462.             self.fillDriverList(self.NPMake, pmodel)
  2463.         
  2464.  
  2465.     
  2466.     def getNPPPD(self):
  2467.         
  2468.         try:
  2469.             if self.rbtnNPFoomatic.isChecked():
  2470.                 nr = self.tvNPDrivers.currentRow()
  2471.                 ppd = self.NPDrivers[nr]
  2472.             elif self.rbtnNPPPD.isChecked():
  2473.                 ppd = cups.PPD(unicode(self.filechooserPPD.getText()))
  2474.             else:
  2475.                 ppd = 'XXX'
  2476.         except RuntimeError:
  2477.             e = None
  2478.             if self.rbtnNPFoomatic.isChecked():
  2479.                 err_title = _('Database error')
  2480.                 err_text = _("The '%s' driver cannot be used with printer '%s %s'.")
  2481.                 (model, iter) = self.tvNPDrivers.get_selection().get_selected()
  2482.                 nr = model.get_path(iter)[0]
  2483.                 driver = self.NPDrivers[nr]
  2484.                 if driver.startswith('gutenprint'):
  2485.                     err = _("You will need to install the '%s' package in order to use this driver.") % 'gutenprint-foomatic'
  2486.                 else:
  2487.                     err = err_text % (driver, self.NPMake, self.NPModel)
  2488.             elif self.rbtnNPPPD.isChecked():
  2489.                 err_title = _('PPD error')
  2490.                 filename = self.filechooserPPD.get_filename()
  2491.                 err = _('Failed to read PPD file.  Possible reason follows:') + '\n'
  2492.                 os.environ['PPD'] = filename
  2493.                 p = os.popen('/usr/bin/cupstestppd -rvv "$PPD"', 'r')
  2494.                 output = p.readlines()
  2495.                 p.close()
  2496.                 err += reduce((lambda x, y: x + y), output)
  2497.             else:
  2498.                 err_title = _('Downloadable drivers')
  2499.                 err_text = _('Support for downloadable drivers is not yet completed.')
  2500.             error_text = '<span weight="bold" size="larger">' + err_title + '</span>\n\n' + err
  2501.             QMessageBox.critical(self, err_title, error_text)
  2502.             return None
  2503.  
  2504.         if isinstance(ppd, str) or isinstance(ppd, unicode):
  2505.             
  2506.             try:
  2507.                 if ppd != 'raw':
  2508.                     f = self.mainapp.cups.getServerPPD(ppd)
  2509.                     ppd = cups.PPD(f)
  2510.                     os.unlink(f)
  2511.             except AttributeError:
  2512.                 nonfatalException()
  2513.                 debugprint('pycups function getServerPPD not available: never mind')
  2514.             except RuntimeError:
  2515.                 nonfatalException()
  2516.                 debugprint('libcups from CUPS 1.3 not available: never mind')
  2517.             except cups.IPPError:
  2518.                 nonfatalException()
  2519.                 debugprint('CUPS 1.3 server not available: never mind')
  2520.             except:
  2521.                 None<EXCEPTION MATCH>AttributeError
  2522.             
  2523.  
  2524.         None<EXCEPTION MATCH>AttributeError
  2525.         return ppd
  2526.  
  2527.     
  2528.     def on_btnNPApply_clicked(self):
  2529.         if self.dialog_mode in ('class', 'printer'):
  2530.             name = unicode(self.entNPName.text())
  2531.             location = unicode(self.entNPLocation.text())
  2532.             info = unicode(self.entNPDescription.text())
  2533.         else:
  2534.             name = self.mainapp.printer.name
  2535.         check = False
  2536.         checkppd = None
  2537.         ppd = self.ppd
  2538.         if self.dialog_mode == 'class':
  2539.             members = self.mainapp.getCurrentClassMembers(self.tvNCMembers)
  2540.             
  2541.             try:
  2542.                 for member in members:
  2543.                     self.passwd_retry = False
  2544.                     self.mainapp.cups.addPrinterToClass(str(member), name)
  2545.             except cups.IPPError:
  2546.                 (e, msg) = None
  2547.                 self.show_IPP_Error(e, msg)
  2548.                 return None
  2549.             except:
  2550.                 None<EXCEPTION MATCH>cups.IPPError
  2551.             
  2552.  
  2553.         None<EXCEPTION MATCH>cups.IPPError
  2554.         if self.dialog_mode == 'printer':
  2555.             self.device.uri = unicode(self.device.uri)
  2556.             uri = None
  2557.             if self.device.uri:
  2558.                 uri = self.device.uri
  2559.             else:
  2560.                 uri = self.getDeviceURI()
  2561.             if not self.ppd:
  2562.                 self.nextNPTab(-1)
  2563.                 return None
  2564.             
  2565.             for option in self.options.itervalues():
  2566.                 option.writeback()
  2567.             
  2568.             self.WaitWindow.setText('<b>' + _('Adding') + '</b><br /><br />' + _('Adding printer'))
  2569.             self.WaitWindow.show()
  2570.             QApplication.processEvents()
  2571.             
  2572.             try:
  2573.                 self.passwd_retry = False
  2574.                 if isinstance(ppd, str) or isinstance(ppd, unicode):
  2575.                     self.mainapp.cups.addPrinter(name, ppdname = ppd, device = uri, info = info, location = location)
  2576.                     check = True
  2577.                 elif ppd is None:
  2578.                     self.mainapp.cups.addPrinter(name, device = uri, info = info, location = location)
  2579.                 else:
  2580.                     cupshelpers.setPPDPageSize(ppd, self.language[0])
  2581.                     self.mainapp.cups.addPrinter(name, ppd = ppd, device = uri, info = info, location = location)
  2582.                     check = True
  2583.                     checkppd = ppd
  2584.                 cupshelpers.activateNewPrinter(self.mainapp.cups, name)
  2585.             except cups.IPPError:
  2586.                 (e, msg) = None
  2587.                 self.WaitWindow.hide()
  2588.                 self.show_IPP_Error(e, msg)
  2589.                 return None
  2590.             except:
  2591.                 self.WaitWindow.hide()
  2592.                 fatalException(1)
  2593.  
  2594.             self.WaitWindow.hide()
  2595.         
  2596.         if self.dialog_mode in ('class', 'printer'):
  2597.             
  2598.             try:
  2599.                 self.passwd_retry = False
  2600.                 self.mainapp.cups.setPrinterLocation(name, location)
  2601.                 self.passwd_retry = False
  2602.                 self.mainapp.cups.setPrinterInfo(name, info)
  2603.             except cups.IPPError:
  2604.                 (e, msg) = None
  2605.                 self.show_IPP_Error(e, msg)
  2606.                 return None
  2607.             except:
  2608.                 None<EXCEPTION MATCH>cups.IPPError
  2609.             
  2610.  
  2611.         None<EXCEPTION MATCH>cups.IPPError
  2612.         if self.dialog_mode == 'device':
  2613.             
  2614.             try:
  2615.                 uri = self.getDeviceURI()
  2616.                 self.mainapp.cups.addPrinter(name, device = uri)
  2617.             except cups.IPPError:
  2618.                 (e, msg) = None
  2619.                 self.show_IPP_Error(e, msg)
  2620.                 return None
  2621.             except:
  2622.                 None<EXCEPTION MATCH>cups.IPPError
  2623.             
  2624.  
  2625.         None<EXCEPTION MATCH>cups.IPPError
  2626.         if self.dialog_mode == 'ppd':
  2627.             if not ppd:
  2628.                 ppd = self.ppd = self.getNPPPD()
  2629.                 if not ppd:
  2630.                     self.nextNPTab(-1)
  2631.                     return None
  2632.                 
  2633.             
  2634.             raw = False
  2635.             if isinstance(ppd, str) or isinstance(ppd, unicode):
  2636.                 if self.rbtnChangePPDasIs.isChecked():
  2637.                     
  2638.                     try:
  2639.                         self.mainapp.cups.addPrinter(name, ppdname = 'raw')
  2640.                     except cups.IPPError:
  2641.                         (e, msg) = None
  2642.                         self.show_IPP_Error(e, msg)
  2643.                     except:
  2644.                         None<EXCEPTION MATCH>cups.IPPError
  2645.                     
  2646.  
  2647.                 None<EXCEPTION MATCH>cups.IPPError
  2648.                 
  2649.                 try:
  2650.                     self.mainapp.cups.addPrinter(name, ppdname = ppd)
  2651.                 except cups.IPPError:
  2652.                     (e, msg) = None
  2653.                     self.show_IPP_Error(e, msg)
  2654.                     return None
  2655.  
  2656.                 
  2657.                 try:
  2658.                     filename = self.mainapp.cups.getPPD(name)
  2659.                     ppd = cups.PPD(filename)
  2660.                     os.unlink(filename)
  2661.                 except cups.IPPError:
  2662.                     (e, msg) = None
  2663.                     if e == cups.IPP_NOT_FOUND:
  2664.                         raw = True
  2665.                     else:
  2666.                         self.show_IPP_Error(e, msg)
  2667.                         return None
  2668.                 except:
  2669.                     e == cups.IPP_NOT_FOUND
  2670.                 
  2671.  
  2672.             None<EXCEPTION MATCH>cups.IPPError
  2673.             if not self.rbtnChangePPDasIs.isChecked():
  2674.                 cupshelpers.copyPPDOptions(self.mainapp.ppd, ppd)
  2675.             else:
  2676.                 for option in self.options.itervalues():
  2677.                     option.writeback()
  2678.                 
  2679.                 cupshelpers.setPPDPageSize(ppd, self.language[0])
  2680.             
  2681.             try:
  2682.                 self.mainapp.cups.addPrinter(name, ppd = ppd)
  2683.             except cups.IPPError:
  2684.                 (e, msg) = None
  2685.                 self.show_IPP_Error(e, msg)
  2686.  
  2687.             if not raw:
  2688.                 check = True
  2689.                 checkppd = ppd
  2690.             
  2691.         
  2692.         self.accept()
  2693.         self.mainapp.populateList(start_printer = name)
  2694.         if check:
  2695.             
  2696.             try:
  2697.                 self.checkDriverExists(name, ppd = checkppd)
  2698.             nonfatalException()
  2699.  
  2700.         
  2701.  
  2702.     on_btnNPApply_clicked = pyqtSignature('')(on_btnNPApply_clicked)
  2703.     
  2704.     def checkDriverExists(self, name, ppd = None):
  2705.         '''Check that the driver for an existing queue actually
  2706.         exists, and prompt to install the appropriate package
  2707.         if not.
  2708.  
  2709.         ppd: cups.PPD object, if already created'''
  2710.         server = cups.getServer()
  2711.         if not server == 'localhost' and server == '127.0.0.1' and server == '::1' or server[0] == '/':
  2712.             return None
  2713.         
  2714.         if not ppd:
  2715.             
  2716.             try:
  2717.                 filename = self.mainapp.cups.getPPD(name)
  2718.             except cups.IPPError:
  2719.                 (e, msg) = None
  2720.                 if e == cups.IPP_NOT_FOUND:
  2721.                     return None
  2722.                 else:
  2723.                     self.show_IPP_Error(e, msg)
  2724.                     return None
  2725.             except:
  2726.                 e == cups.IPP_NOT_FOUND
  2727.  
  2728.             ppd = cups.PPD(filename)
  2729.             os.unlink(filename)
  2730.         
  2731.         (pkgs, exes) = cupshelpers.missingPackagesAndExecutables(ppd)
  2732.         if len(pkgs) > 0 or len(exes) > 0:
  2733.             install = '/usr/bin/system-install-packages'
  2734.             if len(pkgs) > 0 and os.access(install, os.X_OK):
  2735.                 pkg = pkgs[0]
  2736.                 install_text = '<span weight="bold" size="larger">' + _('Install driver') + '</span>\n\n' + _("Printer '%s' requires the %s package but it is not currently installed.") % (name, pkg)
  2737.                 dialog = self.InstallDialog
  2738.                 self.lblInstall.set_markup(install_text)
  2739.             else:
  2740.                 error_text = '<span weight="bold" size="larger">' + _('Missing driver') + '</span>\n\n' + _("Printer '%s' requires the '%s' program but it is not currently installed.  Please install it before using this printer.") % (name, exes + pkgs[0])
  2741.                 QMessageBox.error(self, '', error_text)
  2742.         
  2743.  
  2744.     
  2745.     def on_entNPTIPPQueuename_textChanged(self, ent):
  2746.         self.update_IPP_URI_label()
  2747.  
  2748.     
  2749.     def on_IPPBrowseBox_currentTextChanged(self, text):
  2750.         self.update_IPP_URI_label()
  2751.  
  2752.     
  2753.     def on_btnNPCancel_clicked(self):
  2754.         self.hide()
  2755.  
  2756.     on_btnNPCancel_clicked = pyqtSignature('')(on_btnNPCancel_clicked)
  2757.  
  2758. if __name__ == '__main__':
  2759.     app = QApplication(sys.argv)
  2760.     applet = GUI()
  2761.     sys.exit(app.exec_())
  2762.  
  2763.